2017-08-25 3 views
0

Disons que j'ai une classe simple comme ceci:Créer des délégués de modifier génériquement propriétés/champs dont le type est ICollection <T>

public class SimpleClass 
{ 
    public List<SomeOtherClass> ListOfStuff { get; } = new List<SomeOtherClass>(); 
} 

SimpleClass lui-même est sans importance, disons que je l'ai interrogé le type et a déterminé qu'il est de intérêt pour une raison quelconque, tout ce que j'ai est l'objet System.Type. Maintenant, dites que je veux accéder à toutes les propriétés/champs non statiques de la classe qui implémentent ICollection<T> (c'est-à-dire ListOfStuff sur SimpleClass). Je peux accéder/créer des instances de SimpleClass et je peux également créer dynamiquement des instances de tout ce dont la collection est faite, mais comment puis-je dynamiquement (et aussi efficacement que possible) effacer ou ajouter des éléments à ListOfStuff? Fondamentalement, je veux être en mesure de créer des délégués que je peux appeler plus tard que je peux passer une instance du type intéressé à, et la méthode effacera une propriété/champ spécifique sur cette instance. De même, je veux un autre délégué auquel je peux aussi passer une instance de l'objet de la collection à (par exemple SomeOtherClass dans l'exemple ci-dessus), et il va l'ajouter à la collection sur la propriété.

J'ai la System.Type de la classe que je suis intéressé, je le Je suis intéressé, et je peux créer des instances de la classe et l'élément utilisé dans la collection PropertyInfo/FieldInfo du champ (s) .

par exemple. (ce n'est pas du vrai code!)

Type type = typeof(SimpleClass); 
... 
// CreateNew is a method that somehow returns a new instance of a type 
object test = CreateNew(type); 

// GetCollections somehow returns properties/fields that implement ICollection<> 
foreach(var collection in GetCollections(type)) 
{ 
    // CreateNewCollectionItem somehow returns a new instance of the item used in the collection 
    object newItem = CreateNewCollectionItem(collection); 

    // how do I implement these two lines? 
    var clear = Delegate.CreateDelegate(...); 
    var add = Delegate.CreateDelegate(...); 
    ... 
    clear(test); 
    add(test, newItem); 
} 

Comment puis-je faire ces délégués?

MISE À JOUR: Peut-être que je aurais dû dire « Quel est le meilleur/moyen le plus efficace pour produire ces délégués » au lieu de simplement « comment ». Je suis sûr que je peux écrire du code pour faire ce qui est nécessaire, mais y a-t-il de la magie que je peux utiliser pour améliorer mon code? Expression s peut-être?

MISE À JOUR 2: Je crée mon exemple du type utilisant Expression s et envisage l'aide d'un DynamicMethod ou même TypeBuilder pour créer mes délégués, comme je ne suis pas à la vitesse sur Expression s. Est-ce que quelqu'un a des classes d'assistance/assistance pour ceux-ci comme le code pour les produire n'est pas vraiment lisible ...?

+0

Pour 'CreateNew' vous pouvez trouver https://vagifabilov.wordpress.com/2010/04/02/dont -use-activateur-createinstance-ou-constructorinfo-invoke-utilise-compile-lambda-expressions/d'intérêt. – mjwills

+0

J'ai déjà la plupart du code dont j'ai besoin (y compris 'CreateNew'), mais merci! – MadSkunk

+0

Utilisez https://msdn.microsoft.com/en-us/library/system.reflection.methodinfo.makegenericmethod(v=vs.110).aspx pour appeler une méthode générique avec des types connus uniquement lors de l'exécution. Que diriez-vous de faire 'SimpleClass '? –

Répondre

1

Utilisez typeof(ICollection<>).MakeGenericType() pour obtenir l'interface ICollection<T>, puis la réflexion pour invoquer:

var addMethod = typeof(ICollection<>).MakeGenericType(type).GetMethod("Add"); 
var clearMethod = typeof(ICollection<>).MakeGenericType(type).GetMethod("Clear"); 

clearMethod.Invoke(collection, new object[0]); 
addMethod.Invoke(collection, new object[] { test }); 
+0

Merci, je vais ajouter quelque chose comme ça à mes tests, j'espérais quelque chose de super efficace, mais c'est peut-être le meilleur moyen. – MadSkunk