Может кто-нибудь 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
.
Хорошим примером может быть следующий: например, у вас есть набор регистраторов, и вы позволяете пользователю указывать тип, который будет использоваться во время выполнения, через файл конфигурации.
Затем:
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>()
перегрузкой.