Как создать экземпляр класса, который имеет только закрытый конструктор без параметров в Silverlight? - PullRequest
1 голос
/ 24 сентября 2010

Я работаю над запросом функции для сборщика тестовых данных .NET.Мне нужно иметь возможность создавать экземпляры классов, которые имеют только частные конструкторы без параметров.

Например, мне может потребоваться создать экземпляр следующего класса:

public class MyClass()
{
    private MyClass(){}
}

Для большинства других классов я использую следующий код:

(T)Activator.CreateInstance(typeof(T), true)

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

(T)FormatterServices.GetUninitializedObject(typeof(T))

К сожалению, у меня также есть требование, чтобы эта работа выполнялась в Silverlight, и, к сожалению, в настоящее время Silverlight не содержит System.Runtime.Serialization.FormatterServices.

Кто-нибудь знает что-нибудь в реализации Silverlight, которое позволило бы мне обойти это?Если это не удастся, кто-нибудь знает, как я могу реализовать свою собственную версию этого метода?

Ответы [ 3 ]

1 голос
/ 27 сентября 2010

Оказывается, ответ был прямо передо мной.

Если у вас есть класс, определенный следующим образом:

public class MyClass
{
    private MyClass(){}
}

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

(T)Activator.CreateInstance(typeof(T), true)

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

Получается, мне даже не нужно было использовать FormatterServices.GetUninitializedObject.

Тем не менее, я хотел бы поблагодарить Джона Скита за его ответ, потому что это помогло мне подвергнуть сомнению мой дизайн и углубиться в Activator.CreateInstance и немного улучшить мое понимание создания экземпляров класса.

На данный момент мое решение состоит в том, чтобы исключить использование FormatterServices и просто создать исключение, если что-то пойдет не так при создании типа.

В настоящее время, насколько я могу судить, используя (T) Activator.CreateInstance (typeof (T), true), я должен иметь возможность создавать большинство классов, с которыми я сталкивался, за исключением следующего:

public MyClass()
{
    int a;
    private MyClass(int a)
    {
        this.a = a;
    }
}

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

int argA = 100; 
Type type = typeof(MyClass);

ConstructorInfo c = type.GetConstructor(BindingFlags.NonPublic 
| BindingFlags.Instance, null, new Type[] { typeof(int) }, null);

MyClass o = (MyClass)c.Invoke(new Object[] { argA });

Но, подумав о том, что сказал Джон, я не думаю, что это будет полезно для тех, кто использует построитель тестовых данных, который я улучшаю. Если кто-то приложил много усилий, чтобы предотвратить создание экземпляра класса, то, возможно, он не сможет быть создан иначе, как с помощью средств, предоставленных разработчиком класса.

1 голос
/ 24 сентября 2010

Вы не можете создать экземпляр этого класса извне.Предположительно это было преднамеренно разработано , так что вы не можете создать его экземпляр.

Я бы ожидал, что будет некоторый статический способ получения экземпляров, такой как свойство singleton или фабричный метод.... но если вам нужно сделать это с любым типом, это не сработает.

По сути, вам нужно переосмыслить свой дизайн - не пытайтесьподорвать пожелания автора класса.

0 голосов
/ 24 сентября 2010

Вы можете сделать это, используя отражение, , но

  • вы должны действительно решить, поступаете ли вы правильно.Как и другие говорили, класс, вероятно, разработан так, чтобы его не создавали.Однако я понимаю, что в некоторых редких случаях это может потребоваться.

  • , вам необходимо выполнить это с полным доверием, то есть вне браузера.Вы не можете сделать это внутри браузера.

Вот код:

var privateConstructors = typeof(MyClass).GetConstructors(BindingFlags.NonPublic | BindingFlags.Instance);
foreach (var constr in privateConstructors)
{
    var obj = constr.Invoke(new object[0]);
    return;
}
throw new Exception("private constructor not found");
...