23

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

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 的 content 属性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)

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

更新:

我已经按照建议尝试了这个:

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

结果是一样的。

4

10 回答 10

17

我认为您的电话需要是:

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

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

于 2008-10-16T14:36:37.743 回答
16

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

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

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

于 2008-10-16T15:56:53.820 回答
6

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

于 2008-10-16T15:17:16.553 回答
3

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

public DelayCompositeDesigner(DelayComposite CompositeObject)

...只需使用这个:

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

或者

var designer = Activator.CreateInstance<DelayCompositeDesigner>(new DelayComposite(4));
于 2008-10-16T15:06:38.540 回答
2

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

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

于 2017-02-04T22:25:11.980 回答
1

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

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

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

于 2008-10-16T14:37:34.823 回答
1

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

于 2018-08-14T18:33:20.663 回答
1

就我而言,此代码适用于 .NET Framework,但不适用于 .NET Core 3.1。它抛出ExecutionEngineException这是无法捕捉的。但是当我将目标更改为 .NET 5 时,它可以完美运行。希望这对某人有所帮助。

Type type = assembly.GetType(dllName + ".dll");
Activator.CreateInstance(type ), new Stream[] { stream };
于 2021-07-22T09:15:11.857 回答
0

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

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

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

var designer = Activator.CreateInstance(
    typeof(DelayCompositeDesigner), 
    new object[] { new DelayComposite(4) } 
);
于 2008-10-16T14:39:20.670 回答
0

我找到了解决问题的方法,我正在努力解决同样的问题。

这是我的激活器:

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" });
    }
}
于 2016-12-14T07:34:57.047 回答