Quelqu'un peut-il expliquer le Activator.CreateInstance()
but en détail?
c#.net
façon de faire Object xyz = Class.forName(className).newInstance();
.
Quelqu'un peut-il expliquer le Activator.CreateInstance()
but en détail?
c#.net
façon de faire Object xyz = Class.forName(className).newInstance();
.
Réponses:
Supposons que vous ayez une classe appelée MyFancyObject
comme celle-ci ci-dessous:
class MyFancyObject
{
public int A { get;set;}
}
Il 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 a également de nombreuses autres surcharges telles que la fourniture d'un Type
nom de classe au lieu du nom de classe dans une chaîne. Pourquoi vous auriez un problème comme celui-là est une autre histoire. Voici quelques personnes qui en avaient besoin:
String ClassName = "My.Namespace.MyFancyObject";
).
obj = (MyFancyObject)Activator.CreateInstance("MyAssembly", ClassName))
mais au lieu de lancer avec le type. Cast avec le type fait à partir du ClassName? Comme ça Type type = Type.GetType(ClassName);obj = (type )Activator.CreateInstance("MyAssembly", ClassName))
?
Eh bien, je peux vous donner un exemple pourquoi utiliser quelque chose comme ça. Pensez à un jeu où 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 est de 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 plugins ou d'addins et bien plus encore.
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
Vous pouvez également faire ceci -
var handle = Activator.CreateInstance("AssemblyName",
"Full name of the class including the namespace and class name");
var obj = handle.Unwrap();
.Unwrap()
fait exactement et comment cela se rapporte à d'autres solutions?
CreateInstance
endroit où il revient System.Runtime.Remoting.ObjectHandle
.
Un bon exemple pourrait être le suivant: par exemple, vous avez un ensemble de Loggers et vous autorisez l'utilisateur à spécifier le type à utiliser dans le runtime 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 est celui où vous avez une fabrique d'entités communes, qui crée une entité, et est également responsable de l'initialisation d'une entité par les 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;
}
typeof(loggerType)
résultatsloggerType is a variable and used like a type
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, disons que vous avez le nom du type sous forme de chaîne et que vous souhaitez utiliser la chaîne pour créer une instance de ce type. Vous pouvez utiliser Activator.CreateInstance
pour cela:
string objTypeName = "Foo";
Foo foo = (Foo)Activator.CreateInstance(Type.GetType(objTypeName));
Voici un article MSDN qui explique son application plus en détail:
new Foo()
. Je pense que le PO voulait un exemple plus réaliste.
CreateInstance
est si vous ne connaissez pas le type d'objet que vous allez instancier au moment du design. Dans cet exemple, vous savez clairement qu'il est de type Foo
puisque vous le convertissez en type Foo
. Vous ne feriez jamais cela parce que vous pouvez simplement le faire Foo foo = new Foo()
.
En vous basant sur deepee1 et ceci , 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 il me permet d'attribuer des propriétés, ce qui nous permet de sélectionner et d'opérer dynamiquement sur n'importe quelle table que nous voulons.
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);
Pourquoi l'utiliseriez-vous si vous connaissiez déjà la classe et alliez la lancer? Pourquoi ne pas le faire à l'ancienne et faire de la classe comme vous le faites toujours? Il n'y a aucun avantage à cela sur la façon dont cela se fait normalement. Existe-t-il un moyen de prendre le texte et de l'utiliser 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 énorme avantage à la méthode Magic si elle existe.
Couplé à la réflexion, j'ai trouvé Activator.CreateInstance très utile pour mapper le résultat d'une procédure stockée à une classe personnalisée, comme décrit dans la réponse suivante .
CreateInstance(Type type)
corresponde à laCreateInstance<T>()
surcharge.