Qualcuno può spiegare lo Activator.CreateInstance()
scopo in dettaglio?
c#.net
modo di fare Object xyz = Class.forName(className).newInstance();
.
Qualcuno può spiegare lo Activator.CreateInstance()
scopo in dettaglio?
c#.net
modo di fare Object xyz = Class.forName(className).newInstance();
.
Risposte:
Supponi di avere una classe chiamata MyFancyObject
come questa di seguito:
class MyFancyObject
{
public int A { get;set;}
}
Ti consente di trasformare:
String ClassName = "MyFancyObject";
In
MyFancyObject obj;
utilizzando
obj = (MyFancyObject)Activator.CreateInstance("MyAssembly", ClassName))
e può quindi fare cose come:
obj.A = 100;
Questo è il suo scopo. Ha anche molti altri overload come fornire un Type
invece del nome della classe in una stringa. Perché avresti un problema del genere è una storia diversa. Ecco alcune persone che ne avevano bisogno:
String ClassName = "My.Namespace.MyFancyObject";
).
obj = (MyFancyObject)Activator.CreateInstance("MyAssembly", ClassName))
ma invece di lanciare con il tipo. Cast con il tipo creato da ClassName? Come questo Type type = Type.GetType(ClassName);obj = (type )Activator.CreateInstance("MyAssembly", ClassName))
?
Bene, posso darti un esempio del perché usare qualcosa del genere. Pensa a un gioco in cui vuoi memorizzare il tuo livello e i nemici in un file XML. Quando analizzi questo file, potresti avere un elemento come questo.
<Enemy X="10" Y="100" Type="MyGame.OrcGuard"/>
quello che puoi fare ora è creare dinamicamente gli oggetti trovati nel tuo file di livello.
foreach(XmlNode node in doc)
var enemy = Activator.CreateInstance(null, node.Attributes["Type"]);
Questo è molto utile per costruire ambienti dinamici. Ovviamente è anche possibile usarlo per plugin o scenari aggiuntivi e molto altro ancora.
Il mio buon amico MSDN può spiegartelo, con un esempio
Ecco il codice nel caso in cui il collegamento o il contenuto cambino in futuro:
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
Puoi anche farlo -
var handle = Activator.CreateInstance("AssemblyName",
"Full name of the class including the namespace and class name");
var obj = handle.Unwrap();
.Unwrap()
fa precisamente e come questo si collega ad altre soluzioni?
CreateInstance
dove ritorna System.Runtime.Remoting.ObjectHandle
.
Un buon esempio potrebbe essere il prossimo: ad esempio si dispone di un set di logger e si consente all'utente di specificare il tipo da utilizzare in runtime tramite il file di configurazione.
Poi:
string rawLoggerType = configurationService.GetLoggerType();
Type loggerType = Type.GetType(rawLoggerType);
ILogger logger = Activator.CreateInstance(loggerType.GetType()) as ILogger;
O un altro caso è quando si dispone di una fabbrica di entità comune, che crea entità ed è anche responsabile dell'inizializzazione di un'entità dai dati ricevuti dal DB:
(Pseudocodice)
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)
traduce inloggerType is a variable and used like a type
Il Activator.CreateInstance
metodo crea un'istanza di un tipo specificato utilizzando il costruttore che meglio corrisponde ai parametri specificati.
Ad esempio, supponiamo di avere il nome del tipo come stringa e di voler utilizzare la stringa per creare un'istanza di quel tipo. Potresti usare Activator.CreateInstance
per questo:
string objTypeName = "Foo";
Foo foo = (Foo)Activator.CreateInstance(Type.GetType(objTypeName));
Ecco un articolo di MSDN che spiega la sua applicazione in modo più dettagliato:
new Foo()
. Penso che l'OP volesse un esempio più realistico.
CreateInstance
è se non si conosce il tipo di oggetto che si intende creare in fase di progettazione. In questo esempio, sai chiaramente che è di tipo Foo
poiché lo lanci come tipo Foo
. Non lo faresti mai perché puoi farlo e basta Foo foo = new Foo()
.
Basandosi su deepee1 e questo , ecco come accettare un nome di classe in una stringa e quindi usarlo per leggere e scrivere in un database con LINQ. Uso "dynamic" invece del casting di deepee1 perché mi permette di assegnare proprietà, che ci permette di selezionare dinamicamente e operare su qualsiasi tabella desideriamo.
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);
Perché dovresti usarlo se conoscessi già la classe e volessi lanciarlo? Perché non farlo semplicemente alla vecchia maniera e fare in modo che la classe ce la fai sempre? Non c'è alcun vantaggio in questo rispetto al modo in cui è fatto normalmente. C'è un modo per prendere il testo e operare su di esso in questo modo:
label1.txt = "Pizza"
Magic(label1.txt) p = new Magic(lablel1.txt)(arg1, arg2, arg3);
p.method1();
p.method2();
Se so già che è una pizza non c'è alcun vantaggio a:
p = (Pizza)somefancyjunk("Pizza"); over
Pizza p = new Pizza();
ma vedo un enorme vantaggio nel metodo Magic, se esiste.
Insieme alla riflessione, ho trovato Activator.CreateInstance molto utile per mappare il risultato della stored procedure su una classe personalizzata come descritto nella risposta seguente .
CreateInstance(Type type)
è abbinata alCreateInstance<T>()
sovraccarico.