2009-10-05 7 views
2

Ok, peut-être que ce titre n'a pas beaucoup de sens, mais voici l'affaire. Dire que j'ai une méthode générique avec de multiples contraintes de type, ce ceci:C#: Comment trouver et créer des instances qui remplit plusieurs contraintes de type

public static void DoSomethingAwesome<T>(T thing) 
    where T : IThing, IAwesome, IComparable<T> 
{ 
    ... 
} 

maintenant .... comment puis-je, en utilisant la réflexion, créer quelque chose que je peux envoyer là-dedans?

Si c'était une seule contrainte, je sais que je peux le faire comme ceci:

var types = assembly 
     .GetTypes() 
     .Where(typeof (IThing).IsAssignableFrom) 

foreach(var t in types) 
    DoSomethingAwesome((IThing) Activator.CreateInstance(t)); 

Mais, ne peut pas vraiment jeter à plusieurs interfaces ... comment diable puis-je résoudre ce problème? Vous pourriez dire que je suis à peu près perdu ici maintenant: P

Titre obtenu sorte de long et complexe que je ne savais pas comment appeler cela, s'il vous plaît améliorer si vous pouvez

Répondre

4

Pour ajouter aux réponses de Reed et Loren de trouver des types appropriés, notez que vous serez toujours pas en mesure d'appeler DoSomethingAwesome par coulée, parce que vous avez trouvé, le compilateur ne fournit pas un moyen de convertir l'objet instancié en plusieurs interfaces. Vous avez deux options:

  1. créer une nouvelle interface IAwesomeComparableThing qui dérive de IThing, IAwesome et IComparable <T>, demandez à vos types qui mettent en œuvre, et CAST pour que.

  2. Appelez DoSomethingAwesome via réflexion. Pour ce faire, vous besoin d'obtenir la MethodInfo pour la méthode générique DoSomethingAwesome, puis appelez MethodInfo.MakeGenericMethod avec votre type qui implémente les trois interfaces.

Exemple 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 }); 
+0

type que j'ai reçu de Reed? – Svish

+0

Désolé, je ne voulais pas reproduire les réponses de Reed et Loren sur la façon de localiser les types appropriés. Je suppose que, en utilisant les autres réponses, vous pouvez trouver un type approprié et instancier une instance (en utilisant Activator.CreateInstance). Vous passez ensuite ce type à MakeGenericMethod, et l'instance à Invoke. Désolé pour le manque de clarté. – itowlson

+0

Aah, pense que je l'ai eu maintenant. Mais wat est m? devrait-il être mgénérique? – Svish

0

Je devine qu'il ya pour une raison que vous ne pouvez pas faire

var types = assembly 
.GetTypes() 
.Where(typeof (IThing).IsAssignableFrom && typeof (IAwesome).IsAssignableFrom)) 
+0

ne gère pas la contrainte IComparable , mais, ce qui est la plus délicate. –

+0

Pour les instancier, utilisez Activator.CreateInstance comme vous le faites dans la question. Alors vous avez le problème séparé de les passer à la méthode; J'ai posté une réponse qui en parle. – itowlson

+0

Eh bien, je peux, et je le ferai, bien sûr, mais cela va juste * trouver * ces classes. J'aurai encore du mal à les instancier. – Svish

0

Vous avez besoin d'un type assignable à toutes vos contraintes. Les deux premiers sont faciles, mais le troisième est un peu plus compliqué:

// 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)); 
+0

Ceci, autant que je peux voir, m'aide aussi juste à trouver ces types. Ne les instanciant pas d'une manière que je peux les envoyer dans une méthode générique.La méthode 'IsComparable' semble très utile, donc merci pour celle-là :) – Svish

Questions connexes