2012-04-10 5 views
3

인사말 동료 회원, 문제의 상황은입니다 : 내가 발견 생성자을 후손 클래스에 Activator.CreateInstance로를 호출하려고 없지만, 있어보호 된 생성자가있는 객체의 인스턴스를 만들 수 있습니까?

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

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

public class Descendant : BaseClass 
{ 
    // no constructors 
} 

.

에 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 클래스는 기본 클래스의 보호 된 생성자에 대한 통과를 수행하는 public 생성자를 자동으로 제공합니다. 이것은 잘 작동합니다 :

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 내에서 구현할 수 있습니까? 어떻게 든 생성자를 unwrap 할 수 있습니까? – 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