Activator.CreateInstance的目的是什么?

问题描述 投票:102回答:9

有人能详细解释Activator.CreateInstance()的目的吗?

c# .net reflection
9个回答
129
投票

假设您有一个名为MyFancyObject的类,如下所示:

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

它可以让你转:

String ClassName = "MyFancyObject";

MyFancyObject obj;

运用

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

然后可以做类似的事情:

obj.A = 100;

这是它的目的。它还有许多其他重载,例如在字符串中提供Type而不是类名。为什么你会有这样的问题是一个不同的故事。以下是一些需要它的人:


41
投票

那么我可以给你一个例子,为什么要使用这样的东西。想象一下你想要将你的等级和敌人存储在XML文件中的游戏。解析此文件时,您可能有这样的元素。

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

你现在可以做的是,动态创建你的关卡文件中找到的对象。

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

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


11
投票

我的好朋友MSDN can explain it to you, with an example

以下是链接或内容在未来发生变化时的代码:

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

9
投票

你也可以这样做 -

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

7
投票

下一个好例子就是:例如,你有一组记录器,你允许用户通过配置文件指定在运行时使用的类型。

然后:

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

3
投票

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


1
投票

建立了deepee1和this,这里是如何接受字符串中的类名,然后使用它来读取和写入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);

0
投票

如果你已经认识了这门课并准备施展它,你为什么要用它呢?为什么不以老式的方式去做,让像你一样的课程呢?在正常情况下,这没有任何优势。有没有办法接受文本并对其进行操作:

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方法有很大的优势。


0
投票

结合反射,我发现Activator.CreateInstance在将存储过程结果映射到the following answer中描述的自定义类时非常有用。

© www.soinside.com 2019 - 2024. All rights reserved.