Activator.CreateInstance 找不到构造函数(MissingMethodException)

发布于 2024-07-07 23:03:45 字数 3044 浏览 9 评论 0原文

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

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 的“Delay”属性> 实例。

到目前为止,如果我不向构造函数传递任何参数,则效果很好。 设计器创建 DelayCompositeDesigner 的实例并将其分配给 WPF ContentPresenter 的内容属性。

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

public DelayCompositeDesigner(DelayComposite CompositeObject)
{
    InitializeComponent();

    compositeObject = CompositeObject;
}

欢迎建议


@VolkerK

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

<---- foo Vialis.LightLink.Controller.Scenarios.Composites.DelayCompositeDesignerVoid .ctor() Vialis.LightLink.Controller.Scenarios.Composites.DelayCompositeDesignerVoid .ctor(Vialis.LightLink.Controller.Scenarios.Composites.DelayComposite) 参数:Vialis.LightLink.Controller.Scenarios.Composites.DelayComposite foo ---->


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)

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

更新:< /strong>

我已经按照建议尝试过:

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

结果是相同的。

I have a class which has the following constructor

public DelayCompositeDesigner(DelayComposite CompositeObject)
{
    InitializeComponent();

    compositeObject = CompositeObject;  
}

along with a default constructor with no parameters.

Next I'm trying to create an instance, but it only works without parameters:

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

This works just fine, but if I want to pass parameters it does not:

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

This results in an MissingMethodException:

Constructor voor type
Vialis.LightLink.Controller.Scenarios.Composites.DelayCompositeDesigner
was not found

Any ideas here?


The problem is I really need to pass an object during construction.

You see I have a designer which loads all the types that inherit from the CompositeBase. These are then added to a list from which the users can drag them to a designer. Upon doing so an instance of the dragged is added to the designer. Each of these classes have custom properties defined on them:

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

When the user selects an item in the designer, it looks at these attributes in order to load up a designer for that type. For example, in the case of the DelayComposite it would load up a user control which has a label and a slider which allow the user to set the "Delay" property of the DelayComposite instance.

So far this works fine if I don't pass any parameters to the constructor. The designer creates an instance of the DelayCompositeDesigner and assigns it to the content property of a WPF ContentPresenter.

But since that designer needs to modify the properties of the selected DelayComposite
in the designer, I have to pass this instance to it. That is why the constructor looks lie this:

public DelayCompositeDesigner(DelayComposite CompositeObject)
{
    InitializeComponent();

    compositeObject = CompositeObject;
}

Suggestions are welcome


@VolkerK

The result of your code is this:

<---- foo
Vialis.LightLink.Controller.Scenarios.Composites.DelayCompositeDesignerVoid
.ctor()
Vialis.LightLink.Controller.Scenarios.Composites.DelayCompositeDesignerVoid
.ctor(Vialis.LightLink.Controller.Scenarios.Composites.DelayComposite)
param:Vialis.LightLink.Controller.Scenarios.Composites.DelayComposite
foo ---->


Leppie, you were correct, I had for some reason referenced the Composites assembly in my UI application... which is not something I should have done as I was loading it at runtime. The following code works:

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

As you can see the code does not have knowledge of the DelayComposite type.

This solves the current problem, but introduces many new ones for what I want to achieve,
either way thank you and thank you to everyone who has replied here.


As for the following code, suggested by multiple people:

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

The Activator.CreateInstance has a signature that looks like this:

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

So it should accept my code, but I will try the suggested code

UPDATE:

I've tried this as suggested:

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

The result is the same.

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

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

发布评论

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

评论(10

凯凯我们等你回来 2024-07-14 23:03:45

我认为您的电话需要是:

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

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

I would think that your call would need to be:

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

Unless, of course, it is that, in which case the answer is not immediately obvious.

此生挚爱伱 2024-07-14 23:03:45

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

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

我建议您迭代 ConstructorInfo 并对适当的参数执行 paramtype == typeof(DelayComposite)

I think you are dealing with a Type mismatch.

Likely the assembly is referenced in different places, or they are compiled against different versions.

I suggest you iterate through the ConstructorInfo's and do a paramtype == typeof(DelayComposite) on the appropriate parameter.

迟到的我 2024-07-14 23:03:45

虽然我讨厌类似 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 的输出窗口中打印什么?

Though I hate printf-like debugging ...

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

What does that print in the visual studio's output window?

踏雪无痕 2024-07-14 23:03:45

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

public DelayCompositeDesigner(DelayComposite CompositeObject)

...只需使用这个:

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

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

If you want to call this contructor...

public DelayCompositeDesigner(DelayComposite CompositeObject)

...just use this:

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

or

var designer = Activator.CreateInstance<DelayCompositeDesigner>(new DelayComposite(4));
不一样的天空 2024-07-14 23:03:45

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

实例化构造函数带反射的内部类中的参数

I had a similar issue, however my problem was due to the visibility of the constructor. This stack overflow helped me:

Instantiating a constructor with parameters in an internal class with reflection

冬天旳寂寞 2024-07-14 23:03:45

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

When I encountered this problem, I was using a method that returned the parameter list to plug in to Activator.CreateInstance and it had a different number of arguments than the constructor of the object I was trying to create.

小清晰的声音 2024-07-14 23:03:45

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

System.Runtime.Serialization命名空间中,有一个FormatterServices.GetUninitializedObject(type)函数,它将在不调用构造函数的情况下创建一个对象。

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

I discovered another way of creating an instance of an object without calling the constructor at all while answering another question on SF.

In the System.Runtime.Serialization namespace there is a function FormatterServices.GetUninitializedObject(type) that will create an object without calling constructor.

If you look at that function in Reflector you will see it is making an external call. I don't know how black magic is actually happening under the hood. But I did prove to myself that the constructor was never called but the object was instantiated.

无声静候 2024-07-14 23:03:45

就我而言,此代码适用于 .NET Framework,但不适用于 .NET Core 3.1。 它抛出无法捕获的 ExecutionEngineException 。 但是当我将目标更改为 .NET 5 时,它工作得很好。 希望这对某人有所帮助。

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

In my case, this code work good with .NET Framework but does not work in .NET Core 3.1. It throws ExecutionEngineException which is uncatchable. But when I change target to .NET 5, it works perfectly. Hope this help some one.

Type type = assembly.GetType(dllName + ".dll");
Activator.CreateInstance(type ), new Stream[] { stream };
屋顶上的小猫咪 2024-07-14 23:03:45

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

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

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

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

You can use the following overload on CreateInstance:

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

And in your case it'd be (I think):

var designer = Activator.CreateInstance(
    typeof(DelayCompositeDesigner), 
    new object[] { new DelayComposite(4) } 
);
萤火眠眠 2024-07-14 23:03:45

我找到了问题的解决方案,我也遇到了同样的问题。

这是我的激活器:

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

I found a solution to the problem, I was struggling with the same issue.

Here is my activator:

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

And here is my class to activate, note that I had to change the constructor params to objects, the only way I could get it to work.

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" });
    }
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文