Activator.CreateInstance(t, 42, args) не может найти конструктор

Я использую (слегка расширенную версию) следующий код в функции стиля фабричного шаблона:

public class SingleItemNew : CheckoutContext { public BookingContext Data { get; set; } public SingleItemNew(BookingContext data) { Data = data; } } public CheckoutContext findContext(BookingContext data) { Type contextType = Type.GetType("CheckoutProcesses." + data.Case.ToString()); CheckoutContext output = Activator.CreateInstance(contextType, BindingFlags.CreateInstance, new[] { data }) as CheckoutContext; return output; }

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

Метод data.Case.ToString() возвращает имя класса SingleItemNew, конструктор которого принимает один аргумент.

Кто-нибудь знает, в чем проблема?

Привет, Эд


person Ed James    schedule 11.06.2009    source источник


Ответы (4)


Попробуй это:

  Type contextType = Type.GetType("CheckoutProcesses." + data.Case.ToString());
  CheckoutContext output = 
      (CheckoutContext)Activator.CreateInstance(contextType, data);

Причина, по которой ваш код не работает, заключается в том, что Activator.CreateInstance на самом деле не имеет нужной вам перегрузки. Поэтому вы можете задаться вопросом, почему код вообще компилируется! Причина в том, что у него есть перегрузка, которая принимает (Type type, params object[] args), который соответствует вызову вашего метода, поэтому он компилируется, но во время выполнения ищет в вашем типе конструктор, принимающий BindingFlags и BookingContext[], что явно не соответствует вашему типу.

person mmx    schedule 11.06.2009
comment
точно, я, очевидно, не должен читать страницы документации для классов, они лгут! (Документ для Activator.CreateInstance говорит вам использовать (type, object[] params) для вызова конструктора с соответствующим количеством аргументов внутри params!) =D - person Ed James; 11.06.2009
comment
Это не ложь. Он сказал вам указать BindingFlags, если вам это действительно не нужно? ;) - person mmx; 11.06.2009
comment
Нет, но и без него не получится! (Я уже давно этим занимаюсь) =D - person Ed James; 11.06.2009
comment
Кстати, вы всегда можете щелкнуть правой кнопкой мыши имя метода в коде и использовать Go to definition, чтобы увидеть, какая перегрузка разрешена. - person mmx; 11.06.2009
comment
Activator.CreateInstance должен иметь один из самых запутанных наборов перегрузок во всей .NET Framework! - person Patrick McDonald; 11.06.2009
comment
Это определенно заставило бы меня дважды подумать, прежде чем использовать paramarray в любых перегруженных методах. - person Patrick McDonald; 11.06.2009

Является ли конструктор общедоступным?

Является ли единственный параметр типа BookingContext?

Проблема в том, что это явно часть более крупной системы - было бы намного помочь вам, если бы вы могли создать короткая, но полная программа, демонстрирующая проблему. Тогда мы могли бы исправить проблему в этой программе, и вы могли бы перенести свое исправление обратно в вашу реальную систему. В противном случае мы действительно просто догадываемся :(

person Jon Skeet    schedule 11.06.2009

Принимает ли конструктор SingleItemNew BookingContext в качестве параметра? Если он не совпадает точно, он потерпит неудачу:

class ParamType   {    }
class DerivedParamType : ParamType    {    }
class TypeToCreate
{
    public TypeToCreate(DerivedParamType data)
    {
        // do something
    }
}

ParamType args = new ParamType();
// this call will fail: "constructor not found"
object obj = Activator.CreateInstance(typeof(TypeToCreate), new object[] { args });

// this call would work, since the input type matches the constructor
DerivedParamType args = new DerivedParamType();
object obj = Activator.CreateInstance(typeof(TypeToCreate), new object[] { args });
person Fredrik Mörk    schedule 11.06.2009

Это сработало для меня.

Type.GetType("пространство имен.класс, пространство имен");

person Community    schedule 08.09.2009