Активатор.CreateInstance не может найти конструктор (исключение MissingMethodException)

StackOverflow https://stackoverflow.com/questions/208777

Вопрос

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

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.Контроллер.Сценарии.Композиты.DelayCompositeDesigner не найден

Есть какие-нибудь идеи?


Проблема в том, что мне действительно нужно передать объект во время строительства.

Видите ли, у меня есть конструктор, который загружает все типы, наследуемые от CompositeBase.Затем они добавляются в список, из которого пользователи могут перетащить их в конструктор.После этого экземпляр перетаскиваемого файла добавляется в конструктор.Каждый из этих классов имеет определенные для него пользовательские свойства:

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

Когда пользователь выбирает элемент в конструкторе, он просматривает эти атрибуты, чтобы загрузить конструктор для этого типа.Например, в случае DelayComposite это загрузило бы пользовательский элемент управления, у которого есть метка и ползунок, которые позволяют пользователю устанавливать свойство "Задержка" DelayComposite пример.

Пока это работает нормально, если я не передаю конструктору никаких параметров.Разработчик создает экземпляр DelayCompositeDesigner и присваивает его свойству content WPF ContentPresenter.

Но поскольку этому дизайнеру необходимо изменить свойства выбранного DelayComposite в конструкторе я должен передать ему этот экземпляр.Вот почему конструктор выглядит следующим образом:

public DelayCompositeDesigner(DelayComposite CompositeObject)
{
    InitializeComponent();

    compositeObject = CompositeObject;
}

Предложения приветствуются


@VolkerK

Результатом вашего кода является следующее:

<---- foo Vialis.LightLink.Контроллер.Сценарии.Композиты.DelayCompositeDesignerVoid .ctor() Виалис.LightLink.Контроллер.Сценарии.Составные части.DelayCompositeDesignerVoid .ctor(Vialis).LightLink.Контроллер.Сценарии.Составные части.DelayComposite) параметры: Vialis.LightLink.Контроллер.Сценарии.Композиты.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)});

Результат тот же самый.

Это было полезно?

Решение

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

Вероятно, на сборку ссылаются в разных местах, или они скомпилированы для разных версий.

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

Другие советы

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

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

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

Хотя я ненавижу отладку, подобную 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?

Если вы хотите вызвать этот конструктор...

public DelayCompositeDesigner(DelayComposite CompositeObject)

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

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

или

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

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

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

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

В Система. Среда выполнения.Сериализация пространство имен есть функция Службы форматирования.Получаем uninitializedobject(тип) это создаст объект без вызова конструктора.

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

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

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

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

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

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

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

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

И вот мой класс для активации, обратите внимание, что мне пришлось изменить параметры конструктора на objects, единственный способ заставить его работать.

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top