C# Activator.CreateInstance 找不到构造函数 (MissingMethodException)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/208777/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Activator.CreateInstance can't find the constructor (MissingMethodException)
提问by TimothyP
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
:
这导致MissingMethodException
:
Constructor voor type Vialis.LightLink.Controller.Scenarios.Composites.DelayCompositeDesigner was not found
未找到构造函数类型 Vialis.LightLink.Controller.Scenarios.Composites.DelayCompositeDesigner
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:
你看我有一个设计器,它加载从CompositeBase
. 然后将它们添加到一个列表中,用户可以从该列表中将它们拖到设计器中。这样做后,一个被拖动的实例被添加到设计器中。这些类中的每一个都定义了自定义属性:
[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.
当用户在设计器中选择一个项目时,它会查看这些属性以加载该类型的设计器。例如,在这种情况下,DelayComposite
它将加载一个用户控件,该控件具有一个标签和一个滑块,允许用户设置DelayComposite
实例的“延迟”属性。
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
.
到目前为止,如果我没有将任何参数传递给构造函数,这可以正常工作。设计器创建 的实例DelayCompositeDesigner
并将其分配给 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:
但是由于那个设计器需要修改设计器中选择的属性,所以DelayComposite
我必须将这个实例传递给它。这就是为什么构造函数看起来是这样的:
public DelayCompositeDesigner(DelayComposite CompositeObject)
{
InitializeComponent();
compositeObject = CompositeObject;
}
Suggestions are welcome
欢迎提出建议
@VolkerK
@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 ---->
<---- 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:
Leppie,你是对的,出于某种原因,我在我的 UI 应用程序中引用了 Composites 程序集......这不是我在运行时加载它时应该做的事情。以下代码有效:
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.
如您所见,代码不了解DelayComposite
类型。
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
有一个签名,看起来像这样:
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.
结果是一样的。
采纳答案by leppie
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.
我建议你遍历 ConstructorInfo 并paramtype == typeof(DelayComposite)
在适当的参数上做一个。
回答by DocMax
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 isthat, in which case the answer is not immediately obvious.
当然,除非是这样,在这种情况下,答案并不是很明显。
回答by Jason Hymanson
I discovered another way of creating an instance of an object without calling the constructor at all while answeringanother question on SF.
在回答关于 SF 的另一个问题时,我发现了另一种无需调用构造函数即可创建对象实例的方法。
In the System.Runtime.Serializationnamespace there is a function FormatterServices.GetUninitializedObject(type)that will create an object without calling constructor.
在System.Runtime.Serialization命名空间中,有一个函数FormatterServices.GetUninitializedObject(type)将在不调用构造函数的情况下创建一个对象。
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.
如果您在 Reflector 中查看该函数,您将看到它正在进行外部调用。我不知道黑魔法实际上是如何发生在引擎盖下的。但我确实向自己证明了构造函数从未被调用,但对象已被实例化。
回答by Kev
You can use the following overload on CreateInstance:
您可以在 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) }
);
回答by Ishmaeel
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));
回答by VolkerK
Though I hate printf-like debugging ...
虽然我讨厌类似 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));
What does that print in the visual studio's output window?
在 Visual Studio 的输出窗口中打印什么?
回答by Louis Marais
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" });
}
}
回答by DevNull
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
回答by Mike Cheel
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.
当我遇到这个问题时,我使用了一个返回参数列表的方法来插入到 Activator.CreateInstance 并且它的参数数量与我试图创建的对象的构造函数不同。