Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get "Object" return type from Func<MyClass, object>

Let's suppose I have defined Func as follows:

Func<MyClass, object> f = o => o.StringProperty;

or

Func<MyClass, object> f = o => o.Property.SomeMethod();

Is there way to get the actual return type without specifically calling it?

like image 896
Eugene D. Gubenkov Avatar asked Jul 24 '13 14:07

Eugene D. Gubenkov


2 Answers

You can get the return type like this:

f.Method.ReturnType

But this will return you the type object. If you want to get Method or String or something that derives from object, you won't be able to have the information unless you call the method.

Actually you could, but this would mean that you'd have to dissassemble the method core and then analyze it to see what the method can return. But even then, there might be many different return types.

So the answer is: if you want to know that it returns an object, then yes you can, otherwise it's not worth the trouble, and it's better to find another way of doing what you need.

like image 123
ppetrov Avatar answered Oct 06 '22 19:10

ppetrov


Since you are retrieving these Func<MyClass, object> delegates at runtime from other sources, the type information is essentially lost.

Instead, where these functions are defined, you can have the callers essentially encode that type information in a wrapped delegate by taking advantage of the LINQ Expression API (EDIT: Silly me, far more simpler at this point; we already have the generic compile time information):

public class MyClassDelegate
{
    private readonly Func<MyClass, object> Function;

    public Type ReturnType { get; private set; }

    private MyClassDelegate(Func<MyClass, object> function, Type returnType)
    {
        this.Function = function;
        this.ReturnType = returnType;
    }

    public object Invoke(MyClass context)
    {
        return Function(context);
    }

    public static MyClassDelegate Create<TReturnType>(Func<MyClass, TReturnType> function)
    {
        Func<MyClass, object> nonTypedFunction = o => function(o);
        return new MyClassDelegate(nonTypedFunction, typeof(TReturnType));
    }
}

(A derived generic MyClassDelegate<TReturnType> : MyClassDelegate class could be made as well to get around some of the sillyness in the Create method, or avoid value-type boxing, or to have the return type information available at compile time or even by reflecting on whatever MyClassDelegate<TReturnType> is.)

Callers defining the delegates instead of working directly with a Func<MyClass, object> would instead work with this class and define their delegates as:

MyClassDelegate f1 = MyClassDelegate.Create(o => o.StringProperty);
MyClassDelegate f2 = MyClassDelegate.Create(o => o.Property.SomeMethod());

Your API would require a MyClassDelegate, with which you can easily access their types:

Console.WriteLine(f1.ReturnType.FullName); //string
Console.WriteLine(f2.ReturnType.FullName); //whatever `SomeMethod()` is declared to return

Finally, you can invoke the delegates or even create Func<MyClass, object> delegates still:

f1.Invoke(myClassInstance);
Func<MyClass, object> f3 = f1.Invoke;
like image 32
Chris Sinclair Avatar answered Oct 06 '22 17:10

Chris Sinclair