C #: Como encontrar e criar instâncias que cumpre várias restrições de tipo
-
19-09-2019 - |
Pergunta
dizer que tenho um método genérico com várias restrições de tipo, este este:
public static void DoSomethingAwesome<T>(T thing)
where T : IThing, IAwesome, IComparable<T>
{
...
}
Agora .... como posso, usando a reflexão, criar algo que eu possa enviar para lá?
Se fosse apenas uma restrição eu sei que posso fazê-lo como este:
var types = assembly
.GetTypes()
.Where(typeof (IThing).IsAssignableFrom)
foreach(var t in types)
DoSomethingAwesome((IThing) Activator.CreateInstance(t));
Mas, não pode realmente convertido para múltiplas interfaces ... como na terra eu posso resolver isso? Você poderia dizer que eu estou praticamente perdido aqui agora: P
Título tenho tipo de longo e complexo como eu não tinha certeza do que chamar a isto, por favor melhorar se você pode
Solução
Para adicionar respostas de Reed e Loren sobre encontrar tipos adequados, nota que você ainda não será capaz de chamar DoSomethingAwesome por vazamento, porque como você ter encontrado, o compilador não fornece uma maneira de converter o objeto instanciado para várias interfaces. Você tem duas opções:
-
Criar uma nova interface IAwesomeComparableThing que deriva de IThing, e IAwesome IComparable
, ter o seu tipos implementar isso, e convertido para isso. -
Invoke DoSomethingAwesome através reflexão. Para fazer isso, você vai precisa para obter o MethodInfo para o método genérico DoSomethingAwesome, então ligue MethodInfo.MakeGenericMethod com seu tipo que implementa todas três interfaces.
Exemplo de (2):
Type type = sometype; // For example found using reeds method
MethodInfo mgeneric = typeof(Awesomeiser).GetMethod("DoSomethingAwesome");
MethodInfo mspecific = mgeneric.MakeGenericMethod(new [] { type });
mspecific.Invoke(null, new [] { type });
Outras dicas
Eu estou supondo que há algum motivo você não pode fazer
var types = assembly
.GetTypes()
.Where(typeof (IThing).IsAssignableFrom && typeof (IAwesome).IsAssignableFrom))
Você precisa de um tipo que é atribuível a partir de todas as suas limitações. Os dois primeiros são fáceis, mas o terceiro é um pouco mais complicado:
// Using
static bool IsIComparable(Type thing)
{
foreach (Type interfaceType in thing.GetInterfaces())
{
if (interfaceType.IsGenericType && interfaceType.GetGenericTypeDefinition() == typeof (IComparable<>))
{
Type[] arguments = interfaceType.GetGenericArguments();
if (arguments.Length == 1)
{
if (arguments[0] == thing)
return true;
}
}
}
return false;
}
// This returns an enumerable of compatible types:
var types = assembly.GetTypes().Where( t =>
typeof(IThing).IsAssignableFrom(t) &&
typeof(IAwesome).IsAssignableFrom(t) &&
IsIComparable(t) );