Kann jemand den Activator.CreateInstance()
Zweck im Detail erklären ?
c#.net
richtige Vorgehensweise Object xyz = Class.forName(className).newInstance();
.
Kann jemand den Activator.CreateInstance()
Zweck im Detail erklären ?
c#.net
richtige Vorgehensweise Object xyz = Class.forName(className).newInstance();
.
Antworten:
Angenommen, Sie haben eine Klasse MyFancyObject
wie die folgende:
class MyFancyObject
{
public int A { get;set;}
}
Damit können Sie drehen:
String ClassName = "MyFancyObject";
In
MyFancyObject obj;
Verwenden von
obj = (MyFancyObject)Activator.CreateInstance("MyAssembly", ClassName))
und kann dann Sachen machen wie:
obj.A = 100;
Das ist sein Zweck. Es gibt auch viele andere Überladungen, z. B. die Angabe eines Type
anstelle des Klassennamens in einer Zeichenfolge. Warum Sie so ein Problem haben würden, ist eine andere Geschichte. Hier sind einige Leute, die es brauchten:
String ClassName = "My.Namespace.MyFancyObject";
) aufgenommen habe.
obj = (MyFancyObject)Activator.CreateInstance("MyAssembly", ClassName))
aber anstatt mit dem Typ zu gießen. Besetzung mit Typ aus dem Klassennamen? So Type type = Type.GetType(ClassName);obj = (type )Activator.CreateInstance("MyAssembly", ClassName))
?
Nun, ich kann Ihnen ein Beispiel geben, warum Sie so etwas verwenden sollten. Stellen Sie sich ein Spiel vor, in dem Sie Ihr Level und Ihre Feinde in einer XML-Datei speichern möchten. Wenn Sie diese Datei analysieren, haben Sie möglicherweise ein solches Element.
<Enemy X="10" Y="100" Type="MyGame.OrcGuard"/>
Jetzt können Sie die in Ihrer Level-Datei gefundenen Objekte dynamisch erstellen.
foreach(XmlNode node in doc)
var enemy = Activator.CreateInstance(null, node.Attributes["Type"]);
Dies ist sehr nützlich, um dynamische Umgebungen aufzubauen. Natürlich ist es auch möglich, dies für Plugin- oder Addin-Szenarien und vieles mehr zu verwenden.
Mein guter Freund MSDN kann es Ihnen anhand eines Beispiels erklären
Hier ist der Code für den Fall, dass sich der Link oder Inhalt in Zukunft ändert:
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
Sie können dies auch tun -
var handle = Activator.CreateInstance("AssemblyName",
"Full name of the class including the namespace and class name");
var obj = handle.Unwrap();
.Unwrap()
genau funktioniert und wie dies mit anderen Lösungen zusammenhängt?
CreateInstance
wo es zurückkehrt System.Runtime.Remoting.ObjectHandle
.
Ein gutes Beispiel könnte das nächste sein: Zum Beispiel haben Sie eine Reihe von Loggern und Sie können dem Benutzer erlauben, den Typ anzugeben, der zur Laufzeit über die Konfigurationsdatei verwendet werden soll.
Dann:
string rawLoggerType = configurationService.GetLoggerType();
Type loggerType = Type.GetType(rawLoggerType);
ILogger logger = Activator.CreateInstance(loggerType.GetType()) as ILogger;
ODER Ein anderer Fall ist, wenn Sie eine gemeinsame Entitätsfabrik haben, die eine Entität erstellt und auch für die Initialisierung einer Entität durch von DB empfangene Daten verantwortlich ist:
(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)
führt zuloggerType is a variable and used like a type
Die Activator.CreateInstance
Methode erstellt eine Instanz eines angegebenen Typs mit dem Konstruktor, der den angegebenen Parametern am besten entspricht.
Angenommen, Sie haben den Typnamen als Zeichenfolge und möchten mit der Zeichenfolge eine Instanz dieses Typs erstellen. Sie könnten dafür verwenden Activator.CreateInstance
:
string objTypeName = "Foo";
Foo foo = (Foo)Activator.CreateInstance(Type.GetType(objTypeName));
Hier ist ein MSDN-Artikel, in dem die Anwendung ausführlicher erläutert wird:
new Foo()
. Ich denke, das OP wollte ein realistischeres Beispiel.
CreateInstance
ist, wenn Sie den Objekttyp nicht kennen, den Sie zur Entwurfszeit instanziieren möchten. In diesem Beispiel wissen Sie genau, dass es sich um einen Typ handelt, Foo
da Sie ihn als Typ umwandeln Foo
. Sie würden dies niemals tun, weil Sie es einfach tun können Foo foo = new Foo()
.
Aufbauend auf deepee1 und diesem wird hier beschrieben, wie Sie einen Klassennamen in einer Zeichenfolge akzeptieren und ihn dann zum Lesen und Schreiben in eine Datenbank mit LINQ verwenden. Ich verwende "dynamisch" anstelle des Castings von deepee1, da ich damit Eigenschaften zuweisen kann, mit denen wir jede gewünschte Tabelle dynamisch auswählen und bearbeiten können.
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);
Warum würdest du es benutzen, wenn du die Klasse bereits kennst und sie besetzen würdest? Warum machst du es nicht einfach auf die altmodische Art und machst die Klasse so, wie du es immer machst? Dies hat keinen Vorteil gegenüber der normalen Vorgehensweise. Gibt es eine Möglichkeit, den Text so zu bearbeiten:
label1.txt = "Pizza"
Magic(label1.txt) p = new Magic(lablel1.txt)(arg1, arg2, arg3);
p.method1();
p.method2();
Wenn ich bereits weiß, dass es eine Pizza ist, gibt es keinen Vorteil für:
p = (Pizza)somefancyjunk("Pizza"); over
Pizza p = new Pizza();
Aber ich sehe einen großen Vorteil für die Magic-Methode, wenn sie existiert.
In Verbindung mit der Reflexion fand ich Activator.CreateInstance sehr hilfreich, um das Ergebnis einer gespeicherten Prozedur einer benutzerdefinierten Klasse zuzuordnen, wie in der folgenden Antwort beschrieben .
CreateInstance(Type type)
mit derCreateInstance<T>()
Überlastung übereinstimmt .