2008-10-01 12 views
16

Ich habe eine (schlecht geschriebene) Basisklasse, die ich in ein Proxy-Objekt einbinden möchte. Die Basisklasse ähnelt dem folgenden:Wie kann ich verhindern, dass ein Basiskonstruktor von einem Erben in C# aufgerufen wird?

public class BaseClass : SomeOtherBase 
{ 
    public BaseClass() {} 

    public BaseClass(int someValue) {} 

    //...more code, not important here 
} 

und mein Proxy ähnelt:

public BaseClassProxy : BaseClass 
{ 
    public BaseClassProxy(bool fakeOut){} 
} 

Ohne die „Fakeout“ Konstruktor wird der Basiskonstruktor erwartet aufgerufen werden. Allerdings habe ich damit gerechnet, dass es nicht angerufen wird. So oder so, ich brauche entweder eine Möglichkeit, keine Basisklassenkonstruktoren aufzurufen, oder eine andere Möglichkeit, diese (böse) Klasse effektiv zu vertreten.

Antwort

18

Wenn Sie keinen Konstruktor in der Basisklasse explizit aufrufen, wird der parameterlose Konstruktor implizit aufgerufen. Es gibt keine Möglichkeit, eine Klasse zu instanziieren, ohne dass ein Konstruktor aufgerufen wird.

+1

Eigentlich, wenn Sie meinen Kommentar unten lesen, gibt es einen Weg, obwohl ich es in den meisten Fällen nicht empfehlen würde. –

+0

Diese Antwort ist einfach falsch. Vor allem im Lichte der anderen Antwort. – Kobor42

6

Mindestens 1 ctor muss aufgerufen werden. Der einzige Weg, den ich sehe, ist Eindämmung. Lassen Sie die Klasse innerhalb oder auf die andere Klasse verweisen.

+0

Dies ist der Weg, der mir die meisten Ergebnisse bringt. Vielen Dank! – casademora

1

Ich habe Angst, dass nicht Basis Aufruf Konstruktor ist keine Option.

1

Wenn Sie ein BaseClassProxy erstellen Objekt, das es braucht eine Instanz zu schaffen, die es Basisklasse ist, so dass Sie den Basisklassenkonstruktor anrufen müssen, was Sie können doo ist eine wählen weicht zu nennen, wie:

public BaseClassProxy (bool fakeOut) : base (10) {} 

So rufen Sie den zweiten Konstruktor anstelle des ersten Konstruktors auf

4

Ich glaube nicht, dass Sie den Konstruktor aufrufen können. Aber man könnte so etwas tun:

public class BaseClass : SomeOtherBase 
{ 
    public BaseClass() {} 

    protected virtual void Setup() 
    { 
    } 
} 

public BaseClassProxy : BaseClass 
{ 
    bool _fakeOut; 
    protected BaseClassProxy(bool fakeOut) 
    { 
     _fakeOut = fakeOut; 
     Setup(); 
    } 

    public override void Setup() 
    { 
     if(_fakeOut) 
     { 
      base.Setup(); 
     } 
     //Your other constructor code 
    } 
} 
5

Wenn das, was Sie wollen, ist zu nicht Aufruf einer der beiden Basisklassenkonstruktoren, kann dies nicht geschehen.

C# -Klassenkonstruktoren müssen Basisklassenkonstruktoren aufrufen. Wenn Sie keinen explizit anrufen, base() ist impliziert. In Ihrem Beispiel, wenn Sie die Basisklassenkonstruktor zu nennen, ist es das gleiche wie nicht angeben:

public BaseClassProxy : BaseClass 
{ 
    public BaseClassProxy() : base() { } 
} 

Wenn Sie es vorziehen, die andere Basisklassenkonstruktor zu verwenden, die Sie verwenden können:

public BaseClassProxy : BaseClass 
{ 
    public BaseClassProxy() : base(someIntValue) { } 
} 

In jedem Fall wird einer der beiden explizit oder implizit aufgerufen.

0

landete ich so etwas wie dies zu tun:

public class BaseClassProxy : BaseClass 
{ 
    public BaseClass BaseClass { get; private set; } 

    public virtual int MethodINeedToOverride(){} 
    public virtual string PropertyINeedToOverride() { get; protected set; } 
} 

Das hat mich einige der schlechten Praktiken der Basisklasse um.

+2

Der implizite Standardkonstruktor ruft immer noch den parameterlosen Konstruktor von BaseClass auf. – recursive

46

Es gibt eine Möglichkeit, ein Objekt ohne Aufruf von beliebigen Instanzkonstruktoren zu erstellen.

Bevor Sie fortfahren, seien Sie sehr sicher, dass Sie es so machen wollen. In 99% der Fälle ist dies die falsche Lösung.

Dies ist, wie Sie es tun:

FormatterServices.GetUninitializedObject(typeof(MyClass)); 

Nennen Sie es anstelle der Konstruktor des Objekts. Es erstellt und gibt Ihnen eine Instanz zurück, ohne Konstruktoren oder Feldinitialisierer aufzurufen.

Wenn Sie ein Objekt in WCF deserialisieren, verwendet es diese Methode zum Erstellen des Objekts. Wenn das geschieht, werden Konstruktoren und even Feldinitialisierer nicht ausgeführt.

+9

Das ist verrückt. Meine ganze Welt steht auf dem Kopf! – recursive

+2

Welp, das hat mein Problem gelöst! Versuchen Sie, die DB-Aufrufe eines übergeordneten Objektkonstruktors zu vermeiden, wenn Unit-Tests für eine geerbte Klasse ausgeführt werden. – Tarka

+2

FormatterServices.GetUninitializedObject (typeof (MyClass)); wird statische Konstruktoren jedoch immer noch aufrufen. –

0

Konstruktoren sind von Natur aus öffentlich. Verwenden Sie keinen Konstruktor und verwenden Sie einen anderen für die Konstruktion und machen Sie ihn privat. So würden Sie eine Instanz ohne Parameter erstellen und diese Funktion zum Konstruieren Ihrer Objektinstanz aufrufen.

0

Dies ist mein schlampiger erster Versuch bei dieser Antwort. Stimme es ab und ich werde es aufmerksamer machen.

Ich bin mir nicht sicher, was Sie zu erreichen versuchen, aber es klingt wie Sie Schnittstellen fehlen. Sie können auswählen, welche Schnittstellen für Ihren Bedarf sinnvoll sind. Wenn dies zum Testen ist, würden Sie dann etwas wie A.Fake zum Testen verwenden. Wenn Sie detaillierter angeben, was Sie erreichen möchten. Ich könnte wahrscheinlich hilfreicher sein.

public interface IExtractedFromSomeOtherBase{ 
    // this could also be an interface that the other base already implements. 
    /* extracted stuff here */ 
} 
public interface IBaseClass { 
    /* stuff */ 
} 
public interface IBaseClassProxy { 
    /* stuff */ 
} 
public class BaseClass : 
    SomeOtherBase, IExtractedFromSomeOtherBase, IBaseClass 
{ 
    public BaseClass() {} 

    public BaseClass(int someValue) {} 

    //...more code, not important here 
} 
and, my proxy resembles: 

public BaseClassProxy : BaseClass, IBaseClassProxy 
{ 
    public BaseClassProxy(bool fakeOut){} 
}