Expression.Call causes "Static method requires null instance, non-static method requires non-null instance"

7

I have viewed similar SO questions but cannot figure out why mine won't work. I need to convert my Func<string, bool> value to an Expression to be used in the Moq framework but I cannot get passed an error when trying to convert the Func to an Expression.

This is the error:

Static method requires null instance, non-static method requires non-null instance.

This is my sample code:

using System;
using System.Linq.Expressions;

namespace ConsoleApp1
{
    class Program
    {
        public class MyObject
        {
            public void Add<T>(Func<T, bool> value)
            {
                // Line below causes error: Static method requires null instance, 
                // non-static method requires non-null instance.
                Expression<Func<T, bool>> expression =
                    Expression.Lambda<Func<T, bool>>(Expression.Call(value.Method));


                // I need to use the expression for the line below that is commented out
                // (for context reasons I have included this)
                //_myMock.Setup(m => m.MyMethod(key, It.Is(expression))).Returns("test");
            }
        }

        public static void Main(string[] args)
        {
            // Call it using:
            var myObject = new MyObject();
            myObject.Add(new Func<string, bool>(x => x.StartsWith("test")));
        }
    }
}

Not sure if my function is a static or non-static, but I would have thought it was static. I inspected the Func object using the debugger and there is a field called "IsStatic" set to false (value.Method.IsStatic). A bit confused what else to try.

Thank you.

Stack Trace:

System.ArgumentException
  HResult=0x80070057
  Message=Static method requires null instance, non-static method requires non-null instance.
Parameter name: method
  Source=System.Core
  StackTrace:
   at System.Linq.Expressions.Expression.ValidateStaticOrInstanceMethod(Expression instance, MethodInfo method)
   at System.Linq.Expressions.Expression.Call(Expression instance, MethodInfo method, IEnumerable`1 arguments)
   at System.Linq.Expressions.Expression.Call(MethodInfo method, Expression[] arguments)
   at ConsoleApp1.Program.MyObject.Add[T](Func`2 value) in C:\Users\userName\source\repos\ConsoleApp1\ConsoleApp1\Program.cs:line 14
   at ConsoleApp1.Program.Main(String[] args) in C:\Users\userName\source\repos\ConsoleApp1\ConsoleApp1\Program.cs:line 28

c#
lambda
asked on Stack Overflow Sep 3, 2019 by Mayron • edited Sep 3, 2019 by aloisdg moving to codidact.com

1 Answer

2

Your method that you are wrapping in expression call is not static.

enter image description here

To call not static method you would need valid instance to pass as this, and this can get tricky if you actually use some variable from outside of the func. You can inspect the method further and see its declaring type. Instance of it would be required to make the Expression.Call work.


To just do the mock setup, as it is your goal, you could modify your Add method and just get the expression directly

Add<T>(Expression<Func<T, bool>> expression)
{
    _myMock.Setup(m => m.MyMethod(key, It.Is(expression))).Returns("test");
}

and this will just work when called like this:

myObject.Add((string x) => x.StartsWith("test"));

enter image description here

answered on Stack Overflow Sep 3, 2019 by Rafal • edited Sep 3, 2019 by Rafal

User contributions licensed under CC BY-SA 3.0