Come faccio a determinare il valore di un parametro generico sulla mia istanza di classe
-
02-07-2019 - |
Domanda
Ho un'interfaccia marcatore definita come
public interface IExtender<T>
{
}
Ho una classe che implementa IExtender
public class UserExtender : IExtender<User>
In fase di esecuzione ricevo il tipo UserExtender come parametro per il mio metodo di valutazione
public Type Evaluate(Type type) // type == typeof(UserExtender)
Come posso restituire il mio metodo di valutazione
typeof(User)
basato sulla valutazione del runtime. Sono sicuro che sia coinvolta la riflessione, ma non riesco a romperlo.
(Non ero sicuro di come formulare questa domanda. Spero che sia abbastanza chiaro.)
Soluzione 3
Sono andato in questo modo basandomi su alcuni dei bocconcini forniti. Potrebbe essere reso più robusto per gestire più argomenti generici sull'interfaccia .... ma non ne avevo bisogno;)
private static Type SafeGetSingleGenericParameter(Type type, Type interfaceType)
{
if (!interfaceType.IsGenericType || interfaceType.GetGenericArguments().Count() != 1)
return type;
foreach (Type baseInterface in type.GetInterfaces())
{
if (baseInterface.IsGenericType &&
baseInterface.GetGenericTypeDefinition() == interfaceType.GetGenericTypeDefinition())
{
return baseInterface.GetGenericArguments().Single();
}
}
return type;
}
Altri suggerimenti
C'è un esempio di ciò che descrivi nella documentazione MSDN per Metodo GetGenericTypeDefinition . Utilizza il metodo GetGenericArguments .
Type[] typeArguments = t.GetGenericArguments();
Console.WriteLine("\tList type arguments ({0}):", typeArguments.Length);
foreach (Type tParam in typeArguments)
{
Console.WriteLine("\t\t{0}", tParam);
}
Nel tuo esempio penso che vorresti sostituire t
con this
. Se ciò non funziona direttamente, potresti dover fare qualcosa con Metodo GetInterfaces per enumerare le interfacce correnti sul tuo tipo e quindi GetGenericArguments()
dal tipo di interfaccia.
Ho letto la tua domanda in modo completamente diverso rispetto alle altre risposte.
Se la firma di valutazione può essere modificata in:
public Type Evaluate<T>(IExtender<T> it)
{
return typeof(T);
}
Questo non richiede la modifica del codice chiamante, ma richiede che il parametro sia di tipo IExtender<T>
, tuttavia è possibile ottenere facilmente il tipo T
:
// ** compiled and tested
UserExtender ue = new UserExtender();
Type t = Evaluate(ue);
Certamente non è generico come qualcosa che richiede semplicemente un parametro Type
, ma questo è un approccio diverso al problema. Si noti inoltre che esistono Considerazioni sulla sicurezza per Reflection [msdn]