【问题标题】:Activator.CreateInstance can't find the constructor (MissingMethodException)Activator.CreateInstance 找不到构造函数(MissingMethodException)
【发布时间】:2010-09-17 13:12:51
【问题描述】:

我有一个具有以下构造函数的类

public DelayCompositeDesigner(DelayComposite CompositeObject)
{
    InitializeComponent();

    compositeObject = CompositeObject;  
}

还有一个没有参数的默认构造函数。

接下来我正在尝试创建一个实例,但它只能在没有参数的情况下工作:

var designer = Activator.CreateInstance(designerAttribute.Designer);

这很好用,但如果我想传递参数,它不会:

var designer = Activator.CreateInstance(designerAttribute.Designer, new DelayComposite(4));

这会导致MissingMethodException

构造函数类型 Vialis.LightLink.Controller.Scenarios.Composites.DelayCompositeDesigner 没找到

这里有什么想法吗?


问题是我确实需要在构造过程中传递一个对象。

你看我有一个设计器,它加载从CompositeBase 继承的所有类型。然后将它们添加到列表中,用户可以从中将它们拖到设计器中。这样做后,将拖动的实例添加到设计器中。这些类中的每一个都定义了自定义属性:

[CompositeMetaData("Delay","Sets the delay between commands",1)]
[CompositeDesigner(typeof(DelayCompositeDesigner))]
public class DelayComposite : CompositeBase
{
}

当用户在设计器中选择一个项目时,它会查看这些属性以加载该类型的设计器。例如,在DelayComposite 的情况下,它将加载一个用户控件,该控件具有一个标签和一个滑块,允许用户设置DelayComposite 实例的“延迟”属性。

到目前为止,如果我不将任何参数传递给构造函数,这可以正常工作。设计器创建DelayCompositeDesigner 的实例并将其分配给WPF ContentPresenter 的内容属性。

但是既然那个设计师需要修改选中DelayComposite的属性 在设计器中,我必须将此实例传递给它。这就是为什么构造函数看起来是这样的:

public DelayCompositeDesigner(DelayComposite CompositeObject)
{
    InitializeComponent();

    compositeObject = CompositeObject;
}

欢迎提出建议


@VolkerK

你的代码的结果是这样的:


Leppie,你是对的,我出于某种原因在我的 UI 应用程序中引用了 Composites 程序集……这不是我应该做的,因为我是在运行时加载它的。以下代码有效:

object composite = Activator.CreateInstance(item.CompositType,(byte)205);
                    var designer = Activator.CreateInstance(designerAttribute.Designer, composite);

如您所见,代码不知道DelayComposite 类型。

这解决了当前的问题,但为我想要实现的目标引入了许多新问题, 不管怎样,谢谢你,也感谢所有在这里回复的人。


以下代码,多人建议:

var designer = Activator.CreateInstance(
    designerAttribute.Designer, 
    new object[] { new DelayComposite(4) } 
);

Activator.CreateInstance 的签名如下所示:

Activator.CreateInstance(Type type, params object[] obj)

所以它应该接受我的代码,但我会尝试建议的代码

更新:

我已经按照建议尝试了:

var designer = Activator.CreateInstance(designerAttribute.Designer, new object[] { new DelayComposite(4)});

结果是一样的。

【问题讨论】:

  • 蒂莫西 - 我已经修改了我的答案以通过 typeof(DelayCompositeDesigner) ... 或者我仍然缺少一块拼图。
  • 你能详细说明 DesignerAttribute.Designer 的声明方式吗?
  • Timothy - DesignerAttribute.Designer 被声明为 Type 吗?
  • 我遇到了类似的问题,但事实证明没有找到我的构造函数,因为它不是public(哎呀!)

标签: c# .net activator missingmethodexception


【解决方案1】:

在我的情况下,此代码在 .NET Framework 中运行良好,但在 .NET Core 3.1 中无法运行。它抛出 ExecutionEngineException 这是无法捕获的。但是当我将目标更改为 .NET 5 时,它可以完美运行。希望这对某人有所帮助。

Type type = assembly.GetType(dllName + ".dll");
Activator.CreateInstance(type ), new Stream[] { stream };

【讨论】:

    【解决方案2】:

    当我遇到这个问题时,我正在使用一个返回参数列表的方法插入到 Activator.CreateInstance 中,它的参数数量与我尝试创建的对象的构造函数不同。

    【讨论】:

      【解决方案3】:

      我有一个类似的问题,但是我的问题是由于构造函数的可见性。这个堆栈溢出帮助了我:

      Instantiating a constructor with parameters in an internal class with reflection

      【讨论】:

      • 如果无参数构造函数不是公开的可能会导致这个问题。
      【解决方案4】:

      我找到了解决问题的方法,但我也在为同样的问题苦苦挣扎。

      这是我的激活器:

      private void LoadTask(FileInfo dll)
          {
              Assembly assembly = Assembly.LoadFrom(dll.FullName);
      
              foreach (Type type in assembly.GetTypes())
              {
                  var hasInterface = type.GetInterface("ITask") != null;
      
                  if (type.IsClass && hasInterface)
                  {
                      var instance = Activator.CreateInstance(type, _proxy, _context);
                      _tasks.Add(type.Name, (ITask)instance);
                  }
              }
          }
      

      这是我要激活的类,请注意,我必须将构造函数参数更改为对象,这是我让它工作的唯一方法。

      public class CalculateDowntimeTask : Task<CalculateDowntimeTask>
      {
          public CalculateDowntimeTask(object proxy, object context) : 
              base((TaskServiceClient)proxy, (TaskDataDataContext)context) { }
      
          public override void Execute()
          {
              LogMessage(new TaskMessage() { Message = "Testing" });
              BroadcastMessage(new TaskMessage() { Message = "Testing" });
          }
      }
      

      【讨论】:

        【解决方案5】:

        虽然我讨厌类似 printf 的调试...

        public static void foo(Type t, params object[] p)
        {
            System.Diagnostics.Debug.WriteLine("<---- foo");
            foreach(System.Reflection.ConstructorInfo ci in t.GetConstructors())
            {
                System.Diagnostics.Debug.WriteLine(t.FullName + ci.ToString());
            }
            foreach (object o in p)
            {
                System.Diagnostics.Debug.WriteLine("param:" + o.GetType().FullName);
            }
            System.Diagnostics.Debug.WriteLine("foo ---->");
        }
        // ...
        foo(designerAttribute.Designer, new DelayComposite(4));
        var designer = Activator.CreateInstance(designerAttribute.Designer, new DelayComposite(4));
        

        在 Visual Studio 的输出窗口中打印什么?

        【讨论】:

          【解决方案6】:

          我认为您正在处理类型不匹配。

          程序集可能在不同的地方被引用,或者它们是针对不同的版本编译的。

          我建议您遍历 ConstructorInfo 并在适当的参数上执行 paramtype == typeof(DelayComposite)

          【讨论】:

          • 谢谢!类型不匹配是我的问题。 Checked 传递了一个类型错误的构造函数参数(相同的类名,不同的命名空间)
          【解决方案7】:

          如果你想调用这个构造函数...

          public DelayCompositeDesigner(DelayComposite CompositeObject)
          

          ...就用这个吧:

          var designer = Activator.CreateInstance(typeof(DelayCompositeDesigner), new DelayComposite(4));
          

          var designer = Activator.CreateInstance<DelayCompositeDesigner>(new DelayComposite(4));
          

          【讨论】:

          • designerAttribute.Designer 似乎是 =typeof(DelayCompositeDesigner)
          • Ishmaeel - 当他创建 DelayCompositeDesigner 的实例时,他需要使用 DelayCompositeDesigner(DelayComposite CompositeObject)。对于给定的示例,CreateInstance() 没有重载。
          • 确实:designerAttribute.Designer 就是那种类型,因为我不知道前面会是什么我不能使用 = typeof(DelayCompositeDesigner)
          • Kev - CreateInstance 的第二个参数是“params”参数。这意味着您可以使用任意数量的附加参数调用它,而无需将它们包装在 object[] 中。
          • Ishmaeel - 当我第一次阅读时,您一定在原始发布后的几秒钟内更改了答案;无论如何,我要放弃这个了,OP 对问答的反应不是很迅速/即将到来。
          【解决方案8】:

          您可以在 CreateInstance 上使用以下重载:

          public static Object CreateInstance(
              Type type,
              Object[] args
          )
          

          在你的情况下,它会是(我认为):

          var designer = Activator.CreateInstance(
              typeof(DelayCompositeDesigner), 
              new object[] { new DelayComposite(4) } 
          );
          

          【讨论】:

          • 我试过这个,但它不起作用。此外,不需要创建新对象[]
          • 我其实有一个需要新对象[]的情况。我的构造函数中的(单个)参数类型是 Tuple[] 并且只有当我将它作为单个元素 object[] 传递时,它才会找到构造函数。
          【解决方案9】:

          我发现了另一种创建对象实例而不调用构造函数的方法,而answering SF 上的另一个问题。

          System.Runtime.Serialization 命名空间中有一个函数FormatterServices.GetUninitializedObject(type) 将创建一个对象而不调用构造函数。

          如果您在 Reflector 中查看该函数,您会发现它正在进行外部调用。我不知道黑魔法实际上是如何在幕后发生的。但我确实向自己证明了构造函数从未被调用,但对象被实例化了。

          【讨论】:

            【解决方案10】:

            我认为您的电话需要是:

            var designer = Activator.CreateInstance(designerAttribute.Designer, new object[] { new DelayComposite(4) });
            

            当然,除非,在这种情况下答案不会立即显而易见。

            【讨论】:

            • 我不小心使用了List&lt;T&gt; 而不是T[]。谢谢!
            • @ToastyMallows 这也是我的问题。由于Activator.CreateInstance(Type target, param object[] args) 得到一个param 数组,它假定我的List&lt;object&gt;(意味着参数列表)作为单个参数(该列表被强制转换为对象并包装在大小为1的数组中)。
            猜你喜欢
            • 2015-08-27
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2020-12-14
            • 1970-01-01
            • 2023-04-09
            • 1970-01-01
            相关资源
            最近更新 更多