27

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.

nawfal
  • 70,104
  • 56
  • 326
  • 368
TimothyP
  • 21,178
  • 26
  • 94
  • 142
  • Timothy - I've amended my answer to pass typeof(DelayCompositeDesigner) ... or maybe I'm still missing a piece of the jigsaw. – Kev Oct 16 '08 at 15:01
  • Can you expand on the how designerAttribute.Designer is declared? – Kev Oct 16 '08 at 15:18
  • Timothy - is designerAttribute.Designer declared as Type ? – Kev Oct 16 '08 at 15:37
  • I had a similar problem, but it turns out my constructor wasn't being found simply because it was not `public` (oops!) – Cameron Aug 25 '10 at 19:33

10 Answers10

19

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.

DocMax
  • 12,094
  • 7
  • 44
  • 44
  • 1
    I was accidentally using a `List` instead of `T[]`. Thanks! – ToastyMallows Oct 28 '19 at 18:34
  • @ToastyMallows This was also my problem. Since ```Activator.CreateInstance(Type target, param object[] args)``` gets a ```param``` array it assumed my ```List``` (meant to be the list of parameters) as a single parameter (The list was casted to object and wrapped in an array of size 1). – woot ness Oct 19 '21 at 07:30
18

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.

nawfal
  • 70,104
  • 56
  • 326
  • 368
leppie
  • 115,091
  • 17
  • 196
  • 297
  • Thanks! Type mismatch was my issue. Checked was passing a constructor parameter with the wrong type (same class name, different namespace) – Cossens Jul 01 '20 at 23:18
7

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?

nawfal
  • 70,104
  • 56
  • 326
  • 368
VolkerK
  • 95,432
  • 20
  • 163
  • 226
3

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));
Ishmaeel
  • 14,138
  • 9
  • 71
  • 83
  • designerAttribute.Designer seems to be =typeof(DelayCompositeDesigner) – VolkerK Oct 16 '08 at 15:11
  • Ishmaeel - when he's creating an instance of DelayCompositeDesigner he needs to use the DelayCompositeDesigner(DelayComposite CompositeObject). There isn't an overload on CreateInstance() for the example given. – Kev Oct 16 '08 at 15:15
  • Indeed: designerAttribute.Designer is that type, as I have no idea outfront what that will be I cannot use = typeof(DelayCompositeDesigner) – TimothyP Oct 16 '08 at 15:31
  • Kev - second argument of CreateInstance is a "params" argument. Which means you can call it with any number of additional arguments without wrapping them in an object[]. – Ishmaeel Oct 16 '08 at 16:47
  • Ishmaeel - you must've changed the answer within seconds of original posting when I first read; anyhoo I'm giving up on this one, OP isn't really being very responsive/forthcoming to Q&A. – Kev Oct 16 '08 at 17:17
  • @TimothyP - Shorthand for Opening Poster, quicker than typing a name. – Kev Oct 16 '08 at 23:55
3

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

Community
  • 1
  • 1
DevNull
  • 131
  • 7
1

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.

Community
  • 1
  • 1
Jason Jackson
  • 17,016
  • 8
  • 49
  • 74
1

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.

Mike Cheel
  • 12,626
  • 10
  • 72
  • 101
1

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 };
dennis_ler
  • 659
  • 1
  • 9
  • 36
Viettel Solutions
  • 1,519
  • 11
  • 22
0

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) } 
);
Kev
  • 118,037
  • 53
  • 300
  • 385
  • I have tried this, but it does not work. Also, it's not required to create a new object[] – TimothyP Oct 16 '08 at 18:57
  • I actually have a situation where the new object [] is required. The (single) parameter type in my constructor is a Tuple[] and only when I pass it as a single element object[] does it find the constructor. – Han Mar 31 '15 at 13:54
0

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