例如,Activator.CreateInstance 的用途?

有人能详细解释一下 Activator.CreateInstance()的用途吗?

191459 次浏览

我的好朋友 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

Activator.CreateInstance方法使用与指定参数最匹配的构造函数创建指定类型的实例。

例如,假设类型名称为字符串,并且希望使用该字符串创建该类型的实例。你可以使用 Activator.CreateInstance:

string objTypeName = "Foo";
Foo foo = (Foo)Activator.CreateInstance(Type.GetType(objTypeName));

下面是一篇 MSDN 文章,详细解释了它的应用:

Http://msdn.microsoft.com/en-us/library/wccyzw83.aspx

一个很好的例子可能是下一个: 例如,您有一组 Loggers,并允许用户通过配置文件指定要在运行时使用的类型。

然后:

string rawLoggerType = configurationService.GetLoggerType();
Type loggerType = Type.GetType(rawLoggerType);
ILogger logger = Activator.CreateInstance(loggerType.GetType()) as ILogger;

或者,另一种情况是,您有一个公共实体工厂,它创建实体,并且还负责通过从 DB 接收的数据初始化一个实体:

(伪代码)

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;
}

我可以给你们举个例子。想象一下,在一个游戏中,您希望将您的等级和敌人存储在一个 XML 文件中。当您解析这个文件时,您可能会有这样一个元素。

<Enemy X="10" Y="100" Type="MyGame.OrcGuard"/>

现在可以做的是动态创建在级别文件中找到的对象。

foreach(XmlNode node in doc)
var enemy = Activator.CreateInstance(null, node.Attributes["Type"]);

这对于构建动态环境非常有用。当然,它也可以用于插件或插件场景和更多。

假设你有一个类叫做 MyFancyObject,如下所示:

class MyFancyObject
{
public int A { get;set;}
}

它可以让你转身:

String ClassName = "MyFancyObject";

进入

MyFancyObject obj;

吸毒

obj = (MyFancyObject)Activator.CreateInstance("MyAssembly", ClassName))

然后可以做这样的事情:

obj.A = 100;

这就是它的目的。它还有许多其他重载,例如在字符串中提供 Type而不是类名。你为什么会有这样的问题就另当别论了。下面是一些需要它的人:

你也可以这样做-

var handle = Activator.CreateInstance("AssemblyName",
"Full name of the class including the namespace and class name");
var obj = handle.Unwrap();

基于 Deepee1和 这个,下面介绍如何接受字符串中的类名,然后使用它使用 LINQ 对数据库进行读写。我使用“ Dynamic”而不是 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 方法的巨大优势,如果它存在的话。

再加上反射,我找到了激活器。CreateInstance 对于将存储过程结果映射到 以下答案中描述的自定义类非常有帮助。

我们用它来做类似的事情。

public interface IExample
{
void DoSomethingAmazing();
}


public class ExampleA : IExample
{
public void DoSomethingAmazing()
{
Console.WriteLine("AAAA");
}


public void DoA()
{
Console.WriteLine("A")
}
}


public class ExampleB : IExample
{
public void DoSomethingAmazing()
{
Console.WriteLine("BBBB");
}


public void DoB()
{
Console.WriteLine("B")
}
}

然后提供从设置文件序列化的类型

即使在编译之后,我们仍然可以通过使用不同的设置来改变应用程序的行为

例如。

public static class Programm
{
public static void Main()
{
var type = MagicMethodThatReadsASerializedTypeFromTheSettings();
var example = (IExample) Activator.CreateInstance(type);


example.DoSomethingAmazing();


switch(example)
{
case ExampleA a:
a.DoA();
break;


case ExampleB b:
b.DoB();
break;
}
}
}

并且我在一个自定义的多用户序列化中使用它,在这个序列化中我将 RPC (远程过程调用)发送给其他带有参数的设备。

基本上都是必需品

public ISendable
{
public byte[] ToBytes();
public void FromBytes(byte[] bytes);
}


// Converts any ISendable into a byte[] with the content
// typeBytes + contentBytes
public byte[] ToBytes(ISendable toSend)
{
var typeBytes = Encoding.ASCII.GetBytes(toSend.GetType().AssemblyQualifiedName);
var contentBytes = ISendable.ToBytes();


return MagicMethodToCombineByteArrays(typeBytes, contentBytes);
}


// Coonverts back from byte[] to the according ISendable
// by first reading the type, creating the instance and filling it with
// contentBytes
public T FromBytes<T>(byte[] bytes) where T : ISendable
{
MagicMethodToSplitInputBytes(out var typeBytes, out var contentBytes);
var type = Encoding.ASCII.GetString(typeBytes);


var instance = (T) Activator.CreateInstance(type);
instance.FromBytes(contentBytes);


return instance;
}