web-dev-qa-db-fra.com

But de Activator.CreateInstance avec exemple?

Quelqu'un peut-il expliquer le but de Activator.CreateInstance() en détail?

107
Tabriz Atayi

Disons que vous avez une classe appelée MyFancyObject comme celle-ci ci-dessous:

class MyFancyObject
{
 public int A { get;set;}
}

Cela vous permet de tourner:

String ClassName = "MyFancyObject";

Dans

MyFancyObject obj;

En utilisant

obj = (MyFancyObject)Activator.CreateInstance("MyAssembly", ClassName))

et peut ensuite faire des choses comme:

obj.A = 100;

C'est son but. Il comporte également de nombreuses surcharges, telles que fournir un Type à la place du nom de la classe dans une chaîne. Pourquoi vous auriez un problème comme celui-là, c'est une autre histoire. Voici quelques personnes qui en avaient besoin:

135
deepee1

Eh bien, je peux vous donner un exemple pourquoi utiliser quelque chose comme ça. Pensez à un jeu dans lequel vous souhaitez stocker votre niveau et vos ennemis dans un fichier XML. Lorsque vous analysez ce fichier, vous pouvez avoir un élément comme celui-ci.

<Enemy X="10" Y="100" Type="MyGame.OrcGuard"/>

ce que vous pouvez faire maintenant, c’est créer dynamiquement les objets trouvés dans votre fichier de niveau.

foreach(XmlNode node in doc)
   var enemy = Activator.CreateInstance(null, node.Attributes["Type"]);

Ceci est très utile pour créer des environnements dynamiques. Bien sûr, il est également possible de l'utiliser pour des scénarios de plug-ins ou d'addins, etc.

44
dowhilefor

Mon bon ami MSDN peut vous l'expliquer, avec un exemple

Voici le code au cas où le lien ou le contenu changerait à l'avenir:

using System;

class DynamicInstanceList
{
    private static string instanceSpec = "System.EventArgs;System.Random;" +
        "System.Exception;System.Object;System.Version";

    public static void Main()
    {
        string[] instances = instanceSpec.Split(';');
        Array instlist = Array.CreateInstance(typeof(object), instances.Length);
        object item;
        for (int i = 0; i < instances.Length; i++)
        {
            // create the object from the specification string
            Console.WriteLine("Creating instance of: {0}", instances[i]);
            item = Activator.CreateInstance(Type.GetType(instances[i]));
            instlist.SetValue(item, i);
        }
        Console.WriteLine("\nObjects and their default values:\n");
        foreach (object o in instlist)
        {
            Console.WriteLine("Type:     {0}\nValue:    {1}\nHashCode: {2}\n",
                o.GetType().FullName, o.ToString(), o.GetHashCode());
        }
    }
}

// This program will display output similar to the following: 
// 
// Creating instance of: System.EventArgs 
// Creating instance of: System.Random 
// Creating instance of: System.Exception 
// Creating instance of: System.Object 
// Creating instance of: System.Version 
// 
// Objects and their default values: 
// 
// Type:     System.EventArgs 
// Value:    System.EventArgs 
// HashCode: 46104728 
// 
// Type:     System.Random 
// Value:    System.Random 
// HashCode: 12289376 
// 
// Type:     System.Exception 
// Value:    System.Exception: Exception of type 'System.Exception' was thrown. 
// HashCode: 55530882 
// 
// Type:     System.Object 
// Value:    System.Object 
// HashCode: 30015890 
// 
// Type:     System.Version 
// Value:    0.0 
// HashCode: 1048575
12
Claus Jørgensen

Vous pouvez aussi faire ceci -

var handle = Activator.CreateInstance("AssemblyName", 
                "Full name of the class including the namespace and class name");
var obj = handle.Unwrap();
9
William

Un bon exemple pourrait être le suivant: par exemple, vous avez un ensemble de enregistreurs et vous autorisez l’utilisateur à spécifier le type à utiliser au moment de l’exécution via le fichier de configuration.

Ensuite:

string rawLoggerType = configurationService.GetLoggerType();
Type loggerType = Type.GetType(rawLoggerType);
ILogger logger = Activator.CreateInstance(loggerType.GetType()) as ILogger;

OU un autre cas survient lorsque vous avez une fabrique d'entités communes, qui crée une entité et est également responsable de l'initialisation d'une entité à l'aide de données reçues de DB:

(pseudocode)

public TEntity CreateEntityFromDataRow<TEntity>(DataRow row)
 where TEntity : IDbEntity, class
{
   MethodInfo methodInfo = typeof(T).GetMethod("BuildFromDataRow");
   TEntity instance = Activator.CreateInstance(typeof(TEntity)) as TEntity;
   return methodInfo.Invoke(instance, new object[] { row } ) as TEntity;
}
8
sll

Le Activator.CreateInstance méthode crée une instance d'un type spécifié à l'aide du constructeur qui correspond le mieux aux paramètres spécifiés.

Par exemple, supposons que vous ayez le nom du type sous forme de chaîne et que vous souhaitiez utiliser cette chaîne pour créer une instance de ce type. Vous pouvez utiliser Activator.CreateInstance pour ça:

string objTypeName = "Foo";
Foo foo = (Foo)Activator.CreateInstance(Type.GetType(objTypeName));

Voici un article MSDN qui explique son application plus en détail:

http://msdn.Microsoft.com/en-us/library/wccyzw83.aspx

2
James Johnson

En vous basant sur deepee1 et this , voici comment accepter un nom de classe dans une chaîne, puis l'utiliser pour lire et écrire dans une base de données avec LINQ. J'utilise "dynamique" au lieu du casting de deepee1 car cela me permet d'attribuer des propriétés, ce qui nous permet de sélectionner et d'exploiter de manière dynamique toutes les tables souhaitées.

Type tableType = Assembly.GetExecutingAssembly().GetType("NameSpace.TableName");
ITable itable = dbcontext.GetTable(tableType);

//prints contents of the table
foreach (object y in itable) {
    string value = (string)y.GetType().GetProperty("ColumnName").GetValue(y, null);
    Console.WriteLine(value);
}

//inserting into a table
dynamic tableClass = Activator.CreateInstance(tableType);
//Alternative to using tableType, using Tony's tips
dynamic tableClass = Activator.CreateInstance(null, "NameSpace.TableName").Unwrap();
tableClass.Word = userParameter;
itable.InsertOnSubmit(tableClass);
dbcontext.SubmitChanges();

//sql equivalent
dbcontext.ExecuteCommand("INSERT INTO [TableNme]([ColumnName]) VALUES ({0})", userParameter);
1
DharmaTurtle

Pourquoi voudriez-vous l'utiliser si vous connaissiez déjà la classe et alliez la lancer? Pourquoi ne pas le faire comme avant et faire en sorte que le cours soit comme vous le faites toujours? Il n’ya aucun avantage à ce que cela se fasse normalement. Existe-t-il un moyen de prendre le texte et de l'exploiter ainsi:

label1.txt = "Pizza" 
Magic(label1.txt) p = new Magic(lablel1.txt)(arg1, arg2, arg3);
p.method1();
p.method2();

Si je sais déjà que c'est une pizza, il n'y a aucun avantage à:

p = (Pizza)somefancyjunk("Pizza"); over
Pizza p = new Pizza();

mais je vois un avantage énorme à la méthode Magic si elle existe.

0
user8659016

Couplé à la réflexion, j'ai trouvé que Activator.CreateInstance était très utile pour mapper le résultat d'une procédure stockée sur une classe personnalisée, comme décrit dans la section la réponse suivante .

0
usefulBee