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?
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?
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.
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;
Expression
usage really only helps if you want to avoid the generic inference. That is, you could have Create(Expression<Func<MyClass, object>> function)
and still determine the type used. But you may as well take advantage of generic type inference I used in my update. –
Topazolite You can do something close to this by using a generic method to make the compiler infer the type arguments:
static Func<T1, R> Infer<T1, R>(Func<T1, R> f) { return f; }
And then:
var func = Infer((string s) => s.Length);
This will encode the return type into the type of func
at compilation time.
Of course for a more generally applicable solution you would need a bunch of overloads of Infer
to cover Action
and Func
with one, two, three, etc arguments.
If you then want to get the return type at runtime, for any kind of Func
it's as simple as func.Method.ReturnType
as ppetrov has already pointed out.
Func<string, object> f = s => s.Length
and you do Infer(f)
you will get back a Func<string, object>
-- there is no way to recover type information that has been "lost". –
Gladdie Expression<Func<...>>
and reflection instead. –
Gladdie © 2022 - 2024 — McMap. All rights reserved.
string
in the first example, return ofSomeMethod
in the second), however this example would collapse at run-time as the variablef
could be re-assigned. Hypothetically, iff
could not be re-assigned you could statically determine the return type by parsing theFunc
definition. Sounds like a candidate for Roslyn ;-) – FelicitousExpression
API to check the return type: #672468 (this isn't an exact implementation of what you're trying to do, just a related example) – TopazoliteFunc<MyClass, object> f1 = o => o.StringProperty; Func<MyClass, object> f2 = o => f1(o);
? Or evenFunc<MyClass, object> f = o => { throw new NotImplementedException(); };
? :) – Gofff
delegates at runtime and are specifically typed asFunc<MyClass, object>
? Or would a slight change of syntax be ok, something like:MemberInspector<MyClass>.GetReturnType(o => o.StringProperty)
? – TopazoliteMyClassDelegate f = MyClassDelegate.Create(o => o.StringProperty)
rather than the code you posted? – TopazoliteFunc<MyClass, object>
directly? The custom class can have anInvoke
method that can invoke the delegate as well. – Topazolite