web-dev-qa-db-fra.com

Activator.CreateInstance - Comment créer des instances de classes ayant des constructeurs paramétrés

J'ai lu quelques informations en ligne sur ce sujet, mais je n'en ai trouvé aucun qui me convienne .. Ce que j'essaie de faire est de créer une classe d'un type à l'exécution.

J'utilise Activator.CreateInstance qui fonctionne très bien pour les classes avec des constructeurs qui ne contiennent aucun argument. Pour ceux avec des arguments, il lève une exception, y a-t-il un moyen de contourner cela?

Je suis plus qu'heureux de transmettre des valeurs null ou des valeurs vides au ctor tant que je peux créer la classe elle-même.

28
Chris

J'ai finalement fini par faire quelque chose comme ça - certains commentateurs ont de toute façon laissé entendre que cette solution était envisageable.

J'ai essentiellement parcouru tous les constructeurs disponibles et choisi le plus simple. J'ai ensuite créé des données nulles à transmettre au ctor (pour quoi je l'utilise pour cette approche, c'est bien)

Une partie du code ressemble un peu à ceci

// If we have a ctor that requires parameters then pass null values
if (requiresParameters)
{
    List<object> parameters = new List<object>();
    ParameterInfo[] pInfos = constructorInfos[0].GetParameters();

    foreach (ParameterInfo pi in pInfos)
    {
        parameters.Add(createType(pi.ParameterType));
    }

    return constructorInfos[0].Invoke(parameters.ToArray());
}
8
Chris

Il y a une surcharge qui accepte les arguments en tant que params object[]:

object obj = Activator.CreateInstance(typeof(StringBuilder), "abc");

Cela ferait-il? Alternative, vous pouvez utiliser la réflexion pour trouver le constructeur correct:

Type[] argTypes = new Type[] {typeof(string)};
object[] argValues = new object[] {"abc"};
ConstructorInfo ctor = typeof(StringBuilder).GetConstructor(argTypes);
object obj = ctor.Invoke(argValues);
47
Marc Gravell

J'utilise cette méthode pour contourner un problème que j'ai rencontré et elle semble fonctionner exactement comme je l'espérais. :)

object instance = Activator.CreateInstance(
    typeof(OpCode),
    BindingFlags.NonPublic | BindingFlags.Instance,
    default(Binder),
    new object[] { stringname, pop, Push, operand, type, size, s1, s2, ctrl, endsjmpblk, stack },
    default(CultureInfo));
1
Sam Harwell

Activator.CreateInstance a également toute une série de surcharges, que vous pouvez extraire (Type, params object [] args). Fournissez simplement les arguments de constructeur requis au deuxième paramètre de cet appel.

Assurez-vous toutefois de gérer les exceptions ici, car il est facile de passer des paramètres incorrects ou de modifier ultérieurement les constructeurs du type qui les cassent.

0
pezi_pink_squirrel

Comme alternative à Activator.CreateInstance, FastObjectFactory dans les préformes d'URL liées est meilleur qu'Activator (à partir de .NET 4.0 et bien meilleur que .NET 3.5. Aucun test/statistique effectué avec .NET 4.5). Voir l'article StackOverflow pour les statistiques, les informations et le code. Notez que certaines modifications peuvent être nécessaires en fonction du nombre de paramètres ctor. Le code fourni ne permet qu'un paramètre 1 ctor mais peut être modifié pour avoir plus de 1. Voir les commentaires dans le code.

Comment passer les arguments de ctor dans Activator.CreateInstance ou utiliser IL?

0
thames