Activator.CreateInstance 的目的和示例?

发布于 2024-12-07 02:39:43 字数 61 浏览 2 评论 0原文

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

Can someone explain Activator.CreateInstance() purpose in detail?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(11

春风十里 2024-12-14 02:39:43

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

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

它可以让您将:

String ClassName = "MyFancyObject";

转为

MyFancyObject obj;

使用

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

,然后可以执行以下操作:

obj.A = 100;

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

Say you have a class called MyFancyObject like this one below:

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

It lets you turn:

String ClassName = "MyFancyObject";

Into

MyFancyObject obj;

Using

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

and can then do stuff like:

obj.A = 100;

That's its purpose. It also has many other overloads such as providing a Type instead of the class name in a string. Why you would have a problem like that is a different story. Here's some people who needed it:

梦一生花开无言 2024-12-14 02:39:43

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

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

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

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

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

Well i can give you an example why to use something like that. Think of a game where you want to store your level and enemies in an XML file. When you parse this file, you might have an element like this.

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

what you can do now is, create dynamically the objects found in your level file.

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

This is very useful, for building dynamic enviroments. Of course its also possible to use this for Plugin or addin scenarios and alot more.

﹎☆浅夏丿初晴 2024-12-14 02:39:43

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

My good friend MSDN can explain it to you, with an example

Here is the code in case the link or content changes in the future:

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
も星光 2024-12-14 02:39:43

你也可以这样做——

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

You can also do this -

var handle = Activator.CreateInstance("AssemblyName", 
                "Full name of the class including the namespace and class name");
var obj = handle.Unwrap();
赤濁 2024-12-14 02:39:43

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

然后:

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

A good example could be next: for instance you have a set of Loggers and you allows user to specify type to be used in runtime via configuration file.

Then:

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

OR another case is when you have a common entities factory, which creates entity, and is also responsible on initialization of an entity by data received from DB:

(pseudocode)

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;
}
执妄 2024-12-14 02:39:43

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

The Activator.CreateInstance method creates an instance of a specified type using the constructor that best matches the specified parameters.

For example, let's say that you have the type name as a string, and you want to use the string to create an instance of that type. You could use Activator.CreateInstance for this:

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

Here's an MSDN article that explains it's application in more detail:

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

我的奇迹 2024-12-14 02:39:43

基于 Deepee1 和 this,这里是如何接受字符串中的类名,以及然后使用它通过 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);

Building off of deepee1 and this, here's how to accept a class name in a string, and then use it to read and write to a database with LINQ. I use "dynamic" instead of deepee1's casting because it allows me to assign properties, which allows us to dynamically select and operate on any table we want.

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);
无风消散 2024-12-14 02:39:43

结合反射,我发现 Activator.CreateInstance 对于将存储过程结果映射到自定义类非常有帮助,如以下答案。

Coupled with reflection, I found Activator.CreateInstance to be very helpful in mapping stored procedure result to a custom class as described in the following answer.

债姬 2024-12-14 02:39:43

如果您已经知道该课程并打算进行投射,为什么还要使用它呢?
为什么不只是用老式的方式来做,让班级像你一直做的那样呢?与通常的方式相比,这没有任何优势。
有没有一种方法可以获取文本并对其进行操作:

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 方法,它会具有巨大的优势。

Why would you use it if you already knew the class and were going to cast it?
Why not just do it the old fashioned way and make the class like you always make it? There's no advantage to this over the way it's done normally.
Is there a way to take the text and operate on it thusly:

label1.txt = "Pizza" 
Magic(label1.txt) p = new Magic(lablel1.txt)(arg1, arg2, arg3);
p.method1();
p.method2();

If I already know its a Pizza there's no advantage to:

p = (Pizza)somefancyjunk("Pizza"); over
Pizza p = new Pizza();

but I see a huge advantage to the Magic method if it exists.

小嗷兮 2024-12-14 02:39:43

我有一个名为 GetTestQueryValidatorTest的抽象类。在这种情况下,我不知道确切的对象,因此我必须使用 Activator.CreateInstance 进行单元测试。

    public abstract class GetTestQueryValidatorTest<TQuery, TValidator>
    where TQuery : CreateTestCommandValidator
    where TValidator : AbstractValidator<TQuery>
 {
    [Fact]
    public async Task CreateTestQueryValidator_Check_Value()
    {
        //Arrenge
        var sut = Activator.CreateInstance<TValidator>();

        object query;

        query = Activator.CreateInstance(typeof(TQuery),
        TestResultDataConstant.LESS_THAN_ZERO,
        TestResultDataConstant.UPPER_THAN_TEN
        )!;

        //Act
        var result = await sut.TestValidateAsync((TQuery)query!);

        //Assert
        result.Errors.Select(s => s.ErrorMessage).Should().Contain(nameof(ErrorMessage.Code_Minimum_Number_Is_1);
        result.Errors.Select(s => s.ErrorMessage).Should().Contain(nameof(ErrorMessage.Name_Minimum_Is_10));
    }
}
    

I have an abstract class called GetTestQueryValidatorTest<TQuery, TValidator>. In this scenario, I am not aware of the exact object, so I have to use Activator.CreateInstance for unit testing.

    public abstract class GetTestQueryValidatorTest<TQuery, TValidator>
    where TQuery : CreateTestCommandValidator
    where TValidator : AbstractValidator<TQuery>
 {
    [Fact]
    public async Task CreateTestQueryValidator_Check_Value()
    {
        //Arrenge
        var sut = Activator.CreateInstance<TValidator>();

        object query;

        query = Activator.CreateInstance(typeof(TQuery),
        TestResultDataConstant.LESS_THAN_ZERO,
        TestResultDataConstant.UPPER_THAN_TEN
        )!;

        //Act
        var result = await sut.TestValidateAsync((TQuery)query!);

        //Assert
        result.Errors.Select(s => s.ErrorMessage).Should().Contain(nameof(ErrorMessage.Code_Minimum_Number_Is_1);
        result.Errors.Select(s => s.ErrorMessage).Should().Contain(nameof(ErrorMessage.Name_Minimum_Is_10));
    }
}
    
如果没有 2024-12-14 02:39:43

如果您想要创建的类型仅通过老式 COM 类型库或 CLSID 为您所知,那么它会很有用

        Type comType = Type.GetTypeFromCLSID(myComWidget_guid, false);
        myComWidget_object = Activator.CreateInstance(comType);

it's useful if the type of what you want to create is only known to you via an old-school COM type library or CLSID

        Type comType = Type.GetTypeFromCLSID(myComWidget_guid, false);
        myComWidget_object = Activator.CreateInstance(comType);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文