Czy ktoś może Activator.CreateInstance()
szczegółowo wyjaśnić cel?
c#.net
sposób na zrobienie tego Object xyz = Class.forName(className).newInstance();
.
Czy ktoś może Activator.CreateInstance()
szczegółowo wyjaśnić cel?
c#.net
sposób na zrobienie tego Object xyz = Class.forName(className).newInstance();
.
Odpowiedzi:
Załóżmy, że masz zajęcia o nazwie MyFancyObject
takiej jak ta poniżej:
class MyFancyObject
{
public int A { get;set;}
}
Pozwala skręcić:
String ClassName = "MyFancyObject";
W
MyFancyObject obj;
Za pomocą
obj = (MyFancyObject)Activator.CreateInstance("MyAssembly", ClassName))
a potem może robić takie rzeczy jak:
obj.A = 100;
To jest jego cel. Ma również wiele innych przeciążeń, takich jak podawanie Type
zamiast nazwy klasy w ciągu. Dlaczego miałbyś taki problem, to inna historia. Oto kilka osób, które tego potrzebowały:
String ClassName = "My.Namespace.MyFancyObject";
.).
obj = (MyFancyObject)Activator.CreateInstance("MyAssembly", ClassName))
ale zamiast rzucać z typem. Cast z typem wykonanym z ClassName? Jak to Type type = Type.GetType(ClassName);obj = (type )Activator.CreateInstance("MyAssembly", ClassName))
?
Cóż, mogę podać przykład, dlaczego warto używać czegoś takiego. Pomyśl o grze, w której chcesz przechowywać swój poziom i wrogów w pliku XML. Kiedy parsujesz ten plik, możesz mieć taki element.
<Enemy X="10" Y="100" Type="MyGame.OrcGuard"/>
co możesz teraz zrobić, to dynamicznie tworzyć obiekty znalezione w pliku poziomu.
foreach(XmlNode node in doc)
var enemy = Activator.CreateInstance(null, node.Attributes["Type"]);
Jest to bardzo przydatne przy budowaniu dynamicznych środowisk. Oczywiście możliwe jest również użycie tego w scenariuszach wtyczek lub dodatków i nie tylko.
Mój dobry przyjaciel MSDN może ci to wyjaśnić na przykładzie
Oto kod na wypadek zmiany linku lub treści w przyszłości:
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
Możesz też to zrobić -
var handle = Activator.CreateInstance("AssemblyName",
"Full name of the class including the namespace and class name");
var obj = handle.Unwrap();
.Unwrap()
dokładnie robi i jak to się ma do innych rozwiązań?
CreateInstance
którego wraca System.Runtime.Remoting.ObjectHandle
.
Dobry przykład może być następny: na przykład masz zestaw rejestratorów i pozwalasz użytkownikowi określić typ, który ma być używany w środowisku wykonawczym, za pośrednictwem pliku konfiguracyjnego.
Następnie:
string rawLoggerType = configurationService.GetLoggerType();
Type loggerType = Type.GetType(rawLoggerType);
ILogger logger = Activator.CreateInstance(loggerType.GetType()) as ILogger;
LUB inny przypadek to sytuacja, gdy masz wspólną fabrykę jednostek, która tworzy jednostkę i jest również odpowiedzialna za inicjalizację jednostki przez dane otrzymane z DB:
(pseudo kod)
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)
skutkujeloggerType is a variable and used like a type
Activator.CreateInstance
Metoda tworzy instancję określonego typu przy użyciu konstruktora, który najlepiej pasuje do podanych parametrów.
Na przykład, powiedzmy, że masz nazwę typu jako ciąg i chcesz użyć tego ciągu do utworzenia wystąpienia tego typu. Możesz użyć Activator.CreateInstance
do tego:
string objTypeName = "Foo";
Foo foo = (Foo)Activator.CreateInstance(Type.GetType(objTypeName));
Oto artykuł MSDN, który bardziej szczegółowo wyjaśnia jego zastosowanie:
new Foo()
. Myślę, że PO chciał bardziej realistycznego przykładu.
CreateInstance
jest to, że nie znasz typu obiektu, który zamierzasz utworzyć w czasie projektowania. W tym przykładzie wyraźnie wiesz, że jest to typ, Foo
ponieważ rzutujesz go jako typ Foo
. Nigdy byś tego nie zrobił, ponieważ możesz to zrobić Foo foo = new Foo()
.
Opierając się na deepee1 i tym , oto jak zaakceptować nazwę klasy w ciągu, a następnie użyć jej do odczytu i zapisu w bazie danych za pomocą LINQ. Używam „dynamicznego” zamiast rzutowania deepee1, ponieważ pozwala mi przypisywać właściwości, co pozwala nam dynamicznie wybierać i operować na dowolnej tabeli.
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);
Dlaczego miałbyś go używać, skoro znałeś już klasę i zamierzałeś ją obsadzić? Dlaczego nie zrobić tego w staroświecki sposób i sprawić, by klasa była taka, jak zawsze? Nie ma to żadnej przewagi nad sposobem, w jaki jest to robione normalnie. Czy istnieje sposób, aby wziąć tekst i operować na nim w ten sposób:
label1.txt = "Pizza"
Magic(label1.txt) p = new Magic(lablel1.txt)(arg1, arg2, arg3);
p.method1();
p.method2();
Jeśli już wiem, że to pizza, nie ma żadnej korzyści, aby:
p = (Pizza)somefancyjunk("Pizza"); over
Pizza p = new Pizza();
ale widzę ogromną zaletę metody Magic, jeśli taka istnieje.
W połączeniu z refleksją odkryłem, że Activator.CreateInstance jest bardzo pomocny w mapowaniu wyniku procedury składowanej na klasę niestandardową, jak opisano w poniższej odpowiedzi .
CreateInstance(Type type)
jest dopasowana doCreateInstance<T>()
przeciążenia.