Activator.CreateInstance的目的是什么?

Tab*_*ayi 110 .net c# reflection

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

dee*_*ee1 138

假设你有MyFancyObject一个如下所示的类:

class MyFancyObject
{
 public int A { get;set;}
}
Run Code Online (Sandbox Code Playgroud)

它可以让你转:

String ClassName = "MyFancyObject";
Run Code Online (Sandbox Code Playgroud)

MyFancyObject obj;
Run Code Online (Sandbox Code Playgroud)

运用

obj = (MyFancyObject)Activator.CreateInstance("MyAssembly", ClassName))
Run Code Online (Sandbox Code Playgroud)

然后可以做类似的事情:

obj.A = 100;
Run Code Online (Sandbox Code Playgroud)

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

  • 这证明对我有用.在我的例子中,该类位于不同的命名空间中,因此我必须确保将命名空间包含在我的ClassName字符串中(即`String ClassName ="My.Namespace.MyFancyObject";`). (2认同)
  • 您忘记添加 Unwrap()。您也可以输入 null,而不是“MyAssembly”,系统将搜索当前程序集。 (2认同)
  • 如果我只是使用 MyFancyObject obj = new MyFancyObject() ,我可以用更少的代码完成同样的事情。 (2认同)

dow*_*for 44

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

<Enemy X="10" Y="100" Type="MyGame.OrcGuard"/>
Run Code Online (Sandbox Code Playgroud)

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

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

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

  • 我知道它是创建一个类型的新实例,但这是一个很好的简单示例,为什么人们会这样做. (5认同)

Cla*_*sen 12

我的好朋友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
Run Code Online (Sandbox Code Playgroud)

  • 你是对的.就个人而言,我觉得这个原则也可以提供更好的答案.从我目前的项目来看,我常常在脑海中浮现.我通常只想要一个简单而直接的答案,所以我可以继续我离开的地方.我讨厌打开文章,有时甚至链接到其他文章.许多回答者并没有意识到很多人不会带着时间来到这里阅读几篇文章,并进行了大量不必要的介绍和谈话.简要总结一篇好文章的重要部分是我见过的一些最好答案的关键. (11认同)

Wil*_*iam 9

你也可以这样做 -

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

  • 你能否提供一些关于`.Unwrap()`准确做什么以及它与其他解决方案有何关系的补充说明? (2认同)

sll*_*sll 8

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

然后:

string rawLoggerType = configurationService.GetLoggerType();
Type loggerType = Type.GetType(rawLoggerType);
ILogger logger = Activator.CreateInstance(loggerType.GetType()) as ILogger;
Run Code Online (Sandbox Code Playgroud)

或者另一种情况是当你有一个公共实体工厂,它创建实体,并且还负责通过从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;
}
Run Code Online (Sandbox Code Playgroud)


Jam*_*son 5

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

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

string objTypeName = "Foo";
Foo foo = (Foo)Activator.CreateInstance(Type.GetType(objTypeName));
Run Code Online (Sandbox Code Playgroud)

这是一篇 MSDN 文章,更详细地解释了它的应用:

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

  • 或者你可以只使用“new Foo()”。我认为OP想要一个更现实的例子。 (8认同)
  • 我同意@Konrad 的观点。使用“CreateInstance”的原因是如果您不知道在设计时要实例化的对象的类型。在此示例中,您清楚地知道它的类型为“Foo”,因为您将其转换为“Foo”类型。你永远不会这样做,因为你可以只做“Foo foo = new Foo()”。 (2认同)