Problèmes liés à Activator.CreateInstance ()

J’ai une usine qui est supposée créer des objects qui héritent de la classe Foo au moment de l’exécution. Je pense que le type de retour de System.Activator.CreateInstance est identique à celui d’un object qu’il crée, mais à en juger par le message d’erreur suivant, son type de retour est Object.

Erreur 1 Impossible de convertir implicitement le type ‘object’ en ‘cs_sandbox.Foo’. Il existe une conversion explicite (il manque une dissortingbution?) F: \ projects \ cs_sandbox \ Form1.cs 46 24 cs_sandbox

OK, alors peut être me manque-t il un casting, mais

return (t)System.Activator.CreateInstance(t); 

entraîne un autre message d’erreur qui, je dois l’avouer, n’a aucun sens pour moi

Erreur 1 Impossible de trouver le type ou le nom d’espace de nom ‘t’ (il manque une directive using ou une référence d’assembly?) F: \ projects \ cs_sandbox \ Form1.cs 45 25 cs_sandbox

Et voici mon code:

 class Foo { } class FooChild1 : Foo { } class FooChild2 : Foo { } class MyFactory { public static Foo CreateInstance(ssortingng s) { Type t; if (s.StartsWith("abcdef")) { t = typeof(FooChild1); return System.Activator.CreateInstance(t); } else { t = typeof(FooChild2); return System.Activator.CreateInstance(t); } } } 

Comment puis-je réparer ce code? Ou, si ce n’est pas réparable, quels sont les autres moyens de créer des objects qui héritent d’une classe spécifique au moment de l’exécution?

    Vous devez convertir l’object renvoyé en type Foo . Cela n’a pas de sens de le convertir en un type défini dans une variable. Cela devrait être connu du compilateur, car le sharepoint départ de la hiérarchie d’inheritance est de satisfaire la vérification de type statique du compilateur.

     return (Foo)System.Activator.CreateInstance(t); 

    Il existe une version générique, System.Activator.CreateInstance , qui crée un type connu (non une variable de type mais un argument de type ou un type connu de façon statique, dans le dernier cas, cela n’a pas beaucoup de sens):

     return System.Activator.CreateInstance(); 

    J’ai dû utiliser la méthode UnWrap () après l’activation, comme décrit sur MSDN:

     // Creates an instance of MyType defined in the assembly called ObjectHandleAssembly. ObjectHandle obj = domain.CreateInstance("ObjectHandleAssembly", "MyType"); // Unwrapps the proxy to the MyType object created in the other AppDomain. MyType testObj = (MyType)obj.Unwrap(); 

    Comme décrit sur MSDN . De plus, je devais utiliser des parameters comme celui-ci:

      ObjectHandle obj = domain.CreateInstance("Other.Assembly.Name", "Full.Class.Namespace.ClassName"); 

    Après avoir changé de code

    Il suffit de jeter vos résultats sur Foo like

     return System.Activator.CreateInstance(t) as Foo; 

    ou

     return (Foo)System.Activator.CreateInstance(t); 

    Le premier est un peu plus robuste car vous n’obtiendrez pas d’exception si la conversion n’est pas possible. Il retournera simplement null . Mais cela dépend de ce que vous voulez.

    Avant de changer de code

    Avez-vous essayé des génériques?

     public static OutType CreateInstance(ssortingng s) { Type t; if (s.StartsWith("abcdef")) { t = typeof(Bar); return System.Activator.CreateInstance(t) as OutType; } else { t = typeof(Meh); return System.Activator.CreateInstance(t) as OutType; } } 

    Mais vous avez un problème. Dans votre méthode statique existante, vous essayez de renvoyer Bar et Meh qui ne sont aucunement liés à Foo . Ce sera toujours une exception à moins que votre méthode ne retourne également un object ou un type d’ancêtre commun (comme dans le casting).

    Pour contrôler encore plus de types internes, vous pouvez définir plusieurs types génériques que votre méthode utiliserait en interne.

    Je pense que vous devriez probablement faire ceci:

     public static Foo CreateInstance(ssortingng objectIdentifer) { if (objectIdentifier == "Child1") { return (Foo)Activator.CreateInstance("Foo.FooChild1, FooChild1"); } else { return (Foo)Activator.CreateInstance("Foo.FooChild1, FooChild2"); } } 

    Mon point est que dans ce code, la méthode CreateInstance n’a aucune référence directe à l’assembly ou aux assemblys contenant FooChild1 et FooChild2. Dans le code d’origine, vous créez un type en nommant explicitement FooChild1 et FooChild2, afin que vous puissiez simplement les créer au lieu de les activer.

    Cela a-t-il un sens pour vous?

    Je pense que le correct est:

     public static Foo CreateInstance(ssortingng objectIdentifer) { if (objectIdentifier == "Child1") { return (Foo)Activator.CreateInstance(Type.GetType("Foo.FooChild1, FooChild1")); } else { return (Foo)Activator.CreateInstance(Type.GetType("Foo.FooChild1, FooChild2")); } } 

    J’espère que cela peut vous aider

    Peut-être un peu tard mais si je ne connais pas le type (au cas où vous construisez votre propre codeparser), j’utilise Convert.ChangeType

      ssortingng original = "1"; object value; value = Convert.ChangeType(original, typeof(int)); 

    typeof (int) peut être tout type que vous ne connaissez pas en utilisant object.GetType ();