Activator.CreateInstance - 如何创建具有参数化构造函数的类的实例

Posted

技术标签:

【中文标题】Activator.CreateInstance - 如何创建具有参数化构造函数的类的实例【英文标题】:Activator.CreateInstance - How to create instances of classes that have parameterized constructors 【发布时间】:2010-11-20 06:33:09 【问题描述】:

我已经在网上阅读了一些关于这个主题的文章,但没有发现对我有用。 我想做的是创建一个运行时类型的类。

我使用Activator.CreateInstance,它适用于具有不包含参数的构造函数的类。对于那些有参数的人会抛出异常,有没有办法解决这个问题?

只要我可以创建类本身,我就很乐意将空值或空值传递给 ctor。

【问题讨论】:

问题不是重复的,但答案是:***.com/questions/731452/… How to Pass Parameters to Activator.CreateInstance<T>()的可能重复 @JimG。这怎么可能与 8 个月后提出的问题重复? @Yaur:从技术上讲,你是对的;但我更愿意结束这个问题,因为另一个问题的答案是最新的。 【参考方案1】:

有一个接受参数为params object[]的重载:

object obj = Activator.CreateInstance(typeof(StringBuilder), "abc");

这样可以吗?或者,您可以使用反射来找到正确的构造函数:

Type[] argTypes = new Type[] typeof(string);
object[] argValues = new object[] "abc";
ConstructorInfo ctor = typeof(StringBuilder).GetConstructor(argTypes);
object obj = ctor.Invoke(argValues);

【讨论】:

只是出于好奇,从性能的角度来看,这会更好:获取构造函数列表并通过反射调用特定构造函数或直接使用 object[] 调用 Activator.CreateInstance? 我期待 ConstructorInfo 方法。否则它必须考虑哪些值与哪些构造函数兼容 - 特别是如果您传递了“null”等(可能匹配多个构造函数)。 但是你可以计时;-p 实际上,如果性能是一个重要的考虑因素,你可以用一个预编译的 LINQ 表达式(因为这是 .NET 3.5)来表示构造函数。如果你想要一个这样的例子,请告诉我。 @MarcGravell 我刚刚测试过了。 CreateInstance 较慢。 i.stack.imgur.com/kffhE.png【参考方案2】:

我最终做了这样的事情 - 无论如何,一些评论者暗示了这个解决方案。

我基本上遍历了所有可用的构造函数并选择了最简单的。然后我创建了 null 数据以传递给 ctor(因为我在这种方法中使用它很好)

部分代码看起来有点像这样

// If we have a ctor that requires parameters then pass null values
if (requiresParameters)

    List<object> parameters = new List<object>();
    ParameterInfo[] pInfos = constructorInfos[0].GetParameters();

    foreach (ParameterInfo pi in pInfos)
    
        parameters.Add(createType(pi.ParameterType));
    

    return constructorInfos[0].Invoke(parameters.ToArray());

【讨论】:

constructorInfos[0].GetParameters().Select(pi =&gt; createType(pi.ParameterType)).ToArray()【参考方案3】:

我正在使用这种方法绕过an issue I ran into,它似乎完全按照我的希望工作。 :)

object instance = Activator.CreateInstance(
    typeof(OpCode),
    BindingFlags.NonPublic | BindingFlags.Instance,
    default(Binder),
    new object[]  stringname, pop, push, operand, type, size, s1, s2, ctrl, endsjmpblk, stack ,
    default(CultureInfo));

【讨论】:

可以在任何类型上使用...?【参考方案4】:

Activator.CreateInstance 也有一大堆重载,您可能想要检查的是( Type type, params object[] args )。只需将此调用的第二个参数提供所需的构造函数参数即可。

请确保您在这里处理异常,因为很容易传递不正确的参数或稍后在类型的构造函数中更改某些内容,这会破坏它..

【讨论】:

【参考方案5】:

作为 Activator.CreateInstance 的替代方案,链接 url 中的 FastObjectFactory 的性能优于 Activator(从 .NET 4.0 开始,明显优于 .NET 3.5。没有使用 .NET 4.5 进行测试/统计)。有关统计信息、信息和代码,请参阅 *** 帖子。请注意,可能需要根据 ctor 参数的数量进行一些修改。提供的代码只允许 1 个 ctor 参数,但可以修改为超过 1 个。请参阅代码中的 cmets。

How to pass ctor args in Activator.CreateInstance or use IL?

【讨论】:

以上是关于Activator.CreateInstance - 如何创建具有参数化构造函数的类的实例的主要内容,如果未能解决你的问题,请参考以下文章

笔记 Activator.CreateInstance(Type)

Activator.CreateInstance(type) 抛出异常

Activator.CreateInstance - 如何创建具有参数化构造函数的类的实例

ProtoBuf-net AsReference 需要 Activator.CreateInstance 中的公共构造函数?

使用 Activator.CreateInstance() 创建的对象不会等待整个对象在 Release 上初始化

C# Activator.CreateInstance 动态创建类的实例