Activator.CreateInstance не может найти конструктор (MissingMethodException)

У меня есть класс со следующим конструктором

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

Результат вашего кода таков:

‹---- foo Vialis.LightLink.Controller.Scenarios.Composites.DelayCompositeDesignerVoid .ctor () Vialis.LightLink.Controller.Scenarios.Composites.DelayCompositeDesignerVoid .ctor (Vialis.LightLink.Controller.Scenarios.Composites.Delay .LightLink.Controller.Scenarios.Composites.DelayComposite foo ---->


Леппи, вы были правы, я по какой-то причине ссылался на сборку 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)});

Результат тот же.


person TimothyP    schedule 16.10.2008    source источник
comment
Тимоти - я изменил свой ответ, чтобы передать typeof (DelayCompositeDesigner) ... или, может быть, мне все еще не хватает части мозаики.   -  person Kev    schedule 16.10.2008
comment
Не могли бы вы подробнее рассказать о том, как объявляется designerAttribute.Designer?   -  person Kev    schedule 16.10.2008
comment
Тимоти - дизайнерAttribute.Designer объявлен как Type?   -  person Kev    schedule 16.10.2008
comment
У меня была аналогичная проблема, но оказалось, что мой конструктор не был найден просто потому, что он не был public (ой!)   -  person Cameron    schedule 25.08.2010


Ответы (10)


Я думаю, вы имеете дело с несоответствием типов.

Скорее всего, на сборку есть ссылки в разных местах, или они скомпилированы по разным версиям.

Я предлагаю вам пройти через ConstructorInfo и сделать paramtype == typeof(DelayComposite) для соответствующего параметра.

person leppie    schedule 16.10.2008
comment
Спасибо! Несоответствие типов было моей проблемой. Проверено: передавался параметр конструктора неправильного типа (то же имя класса, другое пространство имен) - person Cossens; 02.07.2020

Я бы подумал, что ваш звонок должен быть:

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

Если, конечно, это не , и в этом случае ответ не сразу очевиден.

person DocMax    schedule 16.10.2008
comment
Я случайно использовал List<T> вместо T[]. Спасибо! - person ToastyMallows; 28.10.2019

Хотя я ненавижу отладку в стиле 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));

Что это печатает в окне вывода визуальной студии?

person VolkerK    schedule 16.10.2008

Если вы хотите позвонить этому строителю ...

public DelayCompositeDesigner(DelayComposite CompositeObject)

... просто используйте это:

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

or

var designer = Activator.CreateInstance<DelayCompositeDesigner>(new DelayComposite(4));
person Ishmaeel    schedule 16.10.2008
comment
designerAttribute.Designer кажется = typeof (DelayCompositeDesigner) - person VolkerK; 16.10.2008
comment
Ishmaeel - когда он создает экземпляр DelayCompositeDesigner, ему необходимо использовать DelayCompositeDesigner (DelayComposite CompositeObject). В данном примере нет перегрузки CreateInstance (). - person Kev; 16.10.2008
comment
В самом деле: designerAttribute.Designer - это именно тот тип, поскольку я понятия не имею, что это будет, я не могу использовать = typeof (DelayCompositeDesigner) - person TimothyP; 16.10.2008
comment
Kev - второй аргумент CreateInstance - это аргумент params. Это означает, что вы можете вызывать его с любым количеством дополнительных аргументов, не помещая их в объект []. - person Ishmaeel; 16.10.2008
comment
Ishmaeel - вы, должно быть, изменили ответ в течение нескольких секунд после первоначальной публикации, когда я впервые прочитал; anyhoo Я отказываюсь от этого, OP на самом деле не очень отзывчивый / готовый к Q&A. - person Kev; 16.10.2008
comment
@TimothyP - Сокращение для начального плаката, быстрее, чем ввод имени. - person Kev; 17.10.2008

У меня была аналогичная проблема, но моя проблема была связана с видимостью конструктора. Мне помогло это переполнение стека:

Создание экземпляра конструктора с параметрами во внутреннем классе с отражение

person DevNull    schedule 04.02.2017
comment
Если конструктор без параметров не является общедоступным, это может вызвать эту проблему. - person Zyo; 14.03.2018

Я обнаружил другой способ создания экземпляра объекта без вызова конструктора, пока отвечая на другой вопрос по SF.

В пространстве имен System.Runtime.Serialization есть функция FormatterServices.GetUninitializedObject (type), которая создает объект без вызова конструктора.

Если вы посмотрите на эту функцию в Reflector, вы увидите, что она выполняет внешний вызов. Я не знаю, как черная магия на самом деле творится под капотом. Но я доказал себе, что конструктор никогда не вызывался, но объект был создан.

person Jason Jackson    schedule 16.10.2008

Когда я столкнулся с этой проблемой, я использовал метод, который возвращал список параметров для подключения к Activator.CreateInstance, и у него было другое количество аргументов, чем у конструктора объекта, который я пытался создать.

person Mike Cheel    schedule 14.08.2018

Вы можете использовать следующую перегрузку в CreateInstance:

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

А в вашем случае это будет (я думаю):

var designer = Activator.CreateInstance(
    typeof(DelayCompositeDesigner), 
    new object[] { new DelayComposite(4) } 
);
person Kev    schedule 16.10.2008
comment
Я пробовал это, но это не работает. Также не требуется создавать новый объект [] - person TimothyP; 16.10.2008
comment
У меня действительно есть ситуация, когда требуется новый объект []. Тип (single) параметра в моем конструкторе - Tuple ‹double, double› [], и только когда я передаю его как объект с одним элементом [], он находит конструктор. - person Han; 31.03.2015

Я нашел решение проблемы, боролся с той же проблемой.

Вот мой активатор:

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" });
    }
}
person Louis Marais    schedule 14.12.2016

В моем случае этот код хорошо работает с .NET Framework, но не работает в .NET Core 3.1. Он бросает ExecutionEngineException, который невозможно поймать. Но когда я меняю цель на .NET 5, она работает отлично. Надеюсь, это кому-нибудь поможет.

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