2012-04-10 2 views
3

Приветствую коллег, рассматриваемая ситуация такова:Возможно ли CreateInstance объекта с защищенным конструктором?

public abstract class BaseClass 
{ 
    protected BaseClass() 
    { 
     // some logic here 
    } 

    protected BaseClass(Object parameter) : this() 
    { 
     // some more logic 
    } 
} 

public class Descendant : BaseClass 
{ 
    // no constructors 
} 

Я пытаюсь вызвать Activator.CreateInstance на потомке класса, но не конструктор найден.

Нужно ли мне определить его в классе Descentant?

привязок я использовал следующие: BindingFlags.Instance | BindingFlags.NonPublic

Примечание 1: Я звоню AppDomain.CreateInstanceAndUnwrap() на самом деле, если она должна иметь какое-то влияние.

domain.CreateInstanceAndUnwrap(path, typeName, false, BindingFlags.Instance | 
    BindingFlags.NonPublic, null, new[] { parameter }, null, null); 

Примечание 2: Если я явно определить защищенный конструктор в потомке класса то он работает, но я хотел бы избежать этого, если это возможно.

+0

Проблемы заключается в том Конструкторы фактически не наследуется, поэтому поиска производного типа для них (как вы обнаружили) непродуктивный. – dlev

+0

Я знаю это, но не хочу заставлять других программистов реализовывать этот один конструктор по умолчанию снова и снова (я тоже это ненавижу). – SmartK8

+0

Если вы знаете это, тогда вы также знаете, что вам нужен другой подход. Конструктор, которого вы хотите вызвать, не существует! – dlev

ответ

4

Вы не можете использовать Activator.CreateInstance, но в окружениях полного доверия вы должны иметь возможность находить и вызывать конструктор непосредственно путем отражения.

Фактически, ваш класс Descendant автоматически предоставляет открытый конструктор, который передает проход защищенному конструктору базового класса. Это должно работать нормально:

Activator.CreateInstance(typeof(Descendant)) 

Итак, теперь я понимаю, что вы пытаетесь вызвать конструктор не по умолчанию. К сожалению для вас это просто запрещено. Вызов конструктора в базовом классе напрямую не будет работать, потому что базовый класс является абстрактным. Для создания объекта необходимо создать конструктор (либо автоматически сгенерированный, либо явно определенный) в классе потомков.

Вы можете создать сквозной конструктор класса Descendant, но ваши комментарии заставляют его звучать так, как будто вы пытаетесь избежать принуждения исполнителей к передаче значения в своем конструкторе. То, что вы, вероятно, на самом деле хотите это метод инициализации, который можно вызвать после построения объекта:

// Define other methods and classes here 
public abstract class BaseClass 
{ 
    protected BaseClass() 
    { 
     // some logic here 
    } 

    protected Object Parameter {get; private set;}  

    public virtual void Initialize(Object parameter) 
    { 
     Parameter = _parameter; 
     // some more logic 
    } 
} 
+0

Но можно ли это сделать в AppDomain, я могу как-то развернуть конструктор и вызвать его? – SmartK8

+0

На самом деле это не так. 'CreateInstance' будет специально искать защищенные конструкторы и называть их, если вы его инструктируете. Проблема здесь в том, что производный класс фактически не имеет * никакого * такого конструктора, защищенного или иным образом. – dlev

+0

Обновлен мой ответ. В этом случае класс потомка имеет стандартный конструктор по умолчанию. – StriplingWarrior

1

Что кажется, что вы хотите здесь шаблон строителя, а не конструкторы. Это довольно просто - вы определяете класс (со стандартным конструктором), который «строит» класс, который вы хотите. Что-то вроде этого (примечания: непроверенный код впереди):

public abstract class BaseBuildable : MarshalByRefObject { 
    public String Foo { get; internal set; } 
} 

public class DerivedBuildable : BaseBuildable { } 

public class BuildableBuilder : MarshalByRefObject { 
    private String _foo; 
    public BuildableBuilder WithFoo(String foo) { _foo = foo; return this; } 
    public TBuildable Build<TBuildable>() where TBuildable : BaseBuildable, new() { 
     return new TBuildable { Foo = _foo; } 
    } 
} 

// Used so: 
var builder = domain.CreateInstanceAndUnwrap(.. // yadda yadda, you want a BuildableBuilder 
var buildable = builder.WithFoo("Foo, yo").Build(); 
+0

ОК, но я вижу, что DerivedBuildable по-прежнему является защищенным конструктором? (который я пытаюсь избавиться на самом деле) – SmartK8

+0

Правильно, обновлено, поэтому оно должно работать. Конструкторы были без параметров - просто там, чтобы показать, что я использую конструкторы по умолчанию –

+0

Это выглядит разумно, я буду голосовать за вас и оставить ответ StriplingWarrior, если с вами все в порядке. Я сон (Европа), я разрешу эту проблему завтра. – SmartK8

Смежные вопросы