8

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

9
  • 2
    I assume that's an exception - could you include the full stack trace? If you could include a minimal reproducible example that would really help - at the moment we can't see MyMethod, etc. Commented Sep 3, 2019 at 8:39
  • @JonSkeet included the relevant parts. There is no inner exception either. Commented Sep 3, 2019 at 8:43
  • No, there's still a relevant part that we can't see - how it links up to your code. Is it in the It.Is call? Is it in Expression.Lambda? Is it in _myMock.Setup? Again, a minimal reproducible example would really help. Commented Sep 3, 2019 at 8:46
  • 1
    Okay, I missed that part - removing the Moq aspect would simplify the question, and it would still be best if you could turn this into something we can copy, paste, compile and run. Commented Sep 3, 2019 at 8:49
  • 1
    Definitely better, thanks. (No need to import Moq etc...) In terms of context, I think it's absolutely worth mentioning why you're trying to do something - but that doesn't have to be part of the minimal example if you're not getting that far. Commented Sep 3, 2019 at 9:18

1 Answer 1

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

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks. I wasn't sure that would work with my .NET 4.7 language level but seems to work nicely.
@Mayron I think this is valid since 3.5.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.