Чи може хтось Activator.CreateInstance()
детально пояснити мету?
c#.net
спосіб Object xyz = Class.forName(className).newInstance();
.
Чи може хтось Activator.CreateInstance()
детально пояснити мету?
c#.net
спосіб Object xyz = Class.forName(className).newInstance();
.
Відповіді:
Скажімо, у вас є клас, який називається MyFancyObject
таким:
class MyFancyObject
{
public int A { get;set;}
}
Це дозволяє вам повернути:
String ClassName = "MyFancyObject";
В
MyFancyObject obj;
Використання
obj = (MyFancyObject)Activator.CreateInstance("MyAssembly", ClassName))
а потім можна робити такі речі, як:
obj.A = 100;
Це його призначення. Він також має багато інших перевантажень, таких як надання Type
замість імені класу в рядку. Чому у вас виникне така проблема, це вже інша історія. Ось деякі люди, яким це було потрібно:
String ClassName = "My.Namespace.MyFancyObject";
).
obj = (MyFancyObject)Activator.CreateInstance("MyAssembly", ClassName))
але замість того, щоб робити кастинг із типом. У ролях із типом, зробленим із ClassName? Як це Type type = Type.GetType(ClassName);obj = (type )Activator.CreateInstance("MyAssembly", ClassName))
?
Ну я можу навести вам приклад, чому використовувати щось подібне. Придумайте гру, де ви хочете зберігати свій рівень та ворогів у XML-файлі. Коли ви аналізуєте цей файл, у вас може виникнути такий елемент.
<Enemy X="10" Y="100" Type="MyGame.OrcGuard"/>
тепер ви можете зробити динамічне створення об'єктів, знайдених у вашому файлі рівня.
foreach(XmlNode node in doc)
var enemy = Activator.CreateInstance(null, node.Attributes["Type"]);
Це дуже корисно для побудови динамічних середовищ. Звичайно, можна також використовувати це для сценаріїв плагінів або додатків та багато іншого.
Мій хороший друг MSDN може пояснити це вам на прикладі
Ось код на випадок, якщо посилання або вміст змінюються в майбутньому:
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
Ви також можете це зробити -
var handle = Activator.CreateInstance("AssemblyName",
"Full name of the class including the namespace and class name");
var obj = handle.Unwrap();
.Unwrap()
що саме робить, і як це стосується інших рішень?
CreateInstance
де він повертається System.Runtime.Remoting.ObjectHandle
.
Хорошим прикладом може бути наступний: наприклад, у вас є набір Loggers, і ви можете користувачеві вказати тип, який буде використовуватися під час виконання через файл конфігурації.
Тоді:
string rawLoggerType = configurationService.GetLoggerType();
Type loggerType = Type.GetType(rawLoggerType);
ILogger logger = Activator.CreateInstance(loggerType.GetType()) as ILogger;
АБО інший випадок, коли у вас є загальна фабрика сутностей, яка створює сутність, а також відповідає за ініціалізацію об'єкта за даними, отриманими з БД:
(псевдокод)
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)
результатиloggerType is a variable and used like a type
Activator.CreateInstance
Метод створює екземпляр зазначеного типу , використовуючи конструктор , який найкращим чином відповідає зазначеним параметрам.
Наприклад, скажімо, що у вас є ім'я типу у вигляді рядка, і ви хочете використовувати рядок для створення примірника цього типу. Ви можете використовувати Activator.CreateInstance
для цього:
string objTypeName = "Foo";
Foo foo = (Foo)Activator.CreateInstance(Type.GetType(objTypeName));
Ось стаття MSDN, яка детальніше пояснює його застосування:
new Foo()
. Я думаю, що ОП хотіла більш реалістичного прикладу.
CreateInstance
є те, що ви не знаєте тип об'єкта, який ви збираєтесь інстанціювати під час проектування. У цьому прикладі ви чітко знаєте, що він має тип, Foo
оскільки ви передаєте його як тип Foo
. Ви ніколи цього не зробите, бо можете просто зробити Foo foo = new Foo()
.
Побудова з deepee1 і цього , ось як прийняти ім’я класу в рядку, а потім використовувати його для читання і запису в базу даних з LINQ. Я використовую "динамічний" замість кастингу deepee1, тому що він дозволяє мені призначати властивості, що дозволяє нам динамічно вибирати та працювати з будь-якою таблицею, яку ми хочемо.
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);
Навіщо використовувати його, якщо ви вже знали клас і збиралися його віддати? Чому б просто не зробити це старомодним способом і зробити клас таким, як ви завжди його складаєте? У цьому немає переваги в тому, як це робиться нормально. Чи є спосіб взяти текст і оперувати ним таким чином:
label1.txt = "Pizza"
Magic(label1.txt) p = new Magic(lablel1.txt)(arg1, arg2, arg3);
p.method1();
p.method2();
Якщо я вже знаю його піцу, немає переваги:
p = (Pizza)somefancyjunk("Pizza"); over
Pizza p = new Pizza();
але я бачу величезну перевагу методу Magic, якщо він існує.
У поєднанні з відображенням я виявив, що Activator.CreateInstance дуже корисний для відображення результатів збереженої процедури до користувацького класу, як описано в наступній відповіді .
CreateInstance(Type type)
звідповідалаCreateInstance<T>()
перевантаженню.