2009-03-17 8 views
5

J'utilise LINQ-to-XML pour interroger un fichier pour une liste d'objets. Ils ont tous la même structure (un ensemble d'options, une liste de paramètres de longueur indéterminée). Basé sur leur nom dans le fichier XML, je veux utiliser les paramètres pour des choses entièrement différentes - j'ai donc fait des sous-classes de cet objet.Comment puis-je appeler dynamiquement un constructeur en C#?

Ma question est - comment invoquer dynamiquement le constructeur correct, sans faire quelque chose comme une déclaration de cas? Ou est-ce que la solution pour instancier élégamment différentes sous-classes de XML est ailleurs?

class Object1 
{ 
    string name; 
    OptionObj opt; 
    List<Param> parameters; 
} 

class sonOfObject : Object1 
{ 
    public void ExecuteSomething() 
    { 
     //do something with the parameters 
    } 
} 

class secondSonOfObject : Object1 
{ 
    public void ExecuteSomething() 
    { 
     //do something entirely different with the parameters 
    } 
} 

var query = from x in xmlDoc.Descendants("Object") 
    select new Object 
    { 
     //select the object from the XML 
    } 

Après ce morceau de code que je pourrais utiliser un constructeur de copie pour un sonOfObject de l'objet de requête plus générique. Mais comment puis-je le faire de manière dynamique, basé sur le nom de la classe enfant?

Je sais que vous pouvez obtenir MethodInfo à partir d'un type et l'invoquer ala ...

MethodInfo m = t.GetMethod(someName); 
m.Invoke(yourObj, null); 

Mais cela voudrait dire que je devrais instancier 9 ou 10 de ces objets de classe des enfants (et obtenir le type pour chacun d'eux), et finit toujours dans une sorte de déclaration de cas.

Existe-t-il un moyen plus élégant d'invoquer dynamiquement des constructeurs de classe enfant?

Répondre

3

Pour qu'une classe participe à ce schéma, je le marquerais d'un attribut personnalisé, qui lui donnerait un "nom XML".

Ensuite, utilisez la réflexion pour trouver tous les Type marqués avec cet attribut et placez-les dans un Dictionary<string, Type>. À ce stade, vous devez décider comment vous allez trouver d'autres assemblys qui pourraient apporter des types au système. Une approche simple consiste à rechercher d'autres fichiers avec l'extension .DLL dans le même répertoire.

Ensuite, chaque fois que vous avez chaîne à partir du XML que vous souhaitez utiliser pour créer une instance de la Type correspondant, il suffit de regarder la Type dans le Dictionary par nom et appeler Type.GetConstructor et ConstructorInfo.Invoke. L'avantage de ceci est que l'identifiant dans le XML est séparé de la disposition physique de votre code - vous pouvez déplacer des types dans des assemblages ou les renommer sans invalider les anciens fichiers XML.

+0

+1 Après avoir relu l'OP, je crois que c'est vraiment la meilleure solution. –

7

Activator.CreateInstance vous permet de passer un nom de classe sous forme de chaîne et il vous renverra une nouvelle instance de cette classe.

Questions connexes