Poiché si richiamano questi delegati Func<MyClass, object>
in fase di runtime da altre fonti, le informazioni sul tipo vengono sostanzialmente perse.
Invece, in cui vengono definite queste funzioni, è possibile avere i chiamanti in sostanza, di codificare le informazioni di tipo in un delegato avvolto sfruttando la LINQ Expression API (EDIT: mi sciocco, di gran lunga più semplice, a questo punto, abbiamo già avere le informazioni momento della compilazione generico):
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));
}
}
(Un generico classe derivata MyClassDelegate<TReturnType> : MyClassDelegate
potrebbe essere fatto anche per aggirare alcuni dei sillyness nel metodo Create
, o evitare il valore-tipo di boxe, o di avere il ritorno scrivi le informazioni disponibili al momento della compilazione o anche riflettendo su qualsiasi cosa sia MyClassDelegate<TReturnType>
.)
chiamanti che definiscono i delegati invece di lavorare direttamente con un Func<MyClass, object>
avrebbe invece lavorare con questa classe e definire i loro delegati come:
MyClassDelegate f1 = MyClassDelegate.Create(o => o.StringProperty);
MyClassDelegate f2 = MyClassDelegate.Create(o => o.Property.SomeMethod());
tuo API richiederebbe un MyClassDelegate
, con il quale si può facilmente accedere ai loro tipi :
Console.WriteLine(f1.ReturnType.FullName); //string
Console.WriteLine(f2.ReturnType.FullName); //whatever `SomeMethod()` is declared to return
Infine, è possibile richiamare i delegati o addirittura creare Func<MyClass, object>
delegati ancora:
f1.Invoke(myClassInstance);
Func<MyClass, object> f3 = f1.Invoke;
"Ottieni" il tipo di ritorno esattamente come? Un esempio ipotetico? – Jon
@Jon Penso che dedurre il tipo di ritorno basato sul fatto che il compilatore lo sa ('stringa' nel primo esempio, il ritorno di' SomeMethod' nel secondo), tuttavia questo esempio collasserebbe a run-time come la variabile 'f 'potrebbe essere riassegnato. Ipoteticamente, se 'f' non può essere riassegnato, è possibile determinare staticamente il tipo di ritorno analizzando la definizione' Func'. Sembra un candidato per Roslyn ;-) –
A seconda del tuo utilizzo, forse puoi sfruttare l'API 'Expression' per verificare il tipo di ritorno: http://stackoverflow.com/questions/671968/retrieving-property-name-from- espressione lambda (questa non è un'implementazione esatta di ciò che stai cercando di fare, solo un esempio correlato) –