2008-10-01 7 views
16

J'ai une classe de base (mal écrite) que je veux envelopper dans un objet proxy. La classe de base ressemble à ce qui suit:Comment puis-je empêcher un constructeur de base d'être appelé par un héritage en C#?

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

    public BaseClass(int someValue) {} 

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

et, ma procuration ressemble à:

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

Sans le constructeur "fakeout", le constructeur de base devrait être appelé. Cependant, avec cela, je m'attendais à ce qu'il ne soit pas appelé. D'une manière ou d'une autre, j'ai besoin d'un moyen de ne pas appeler de constructeur de classe de base, ou d'un autre moyen de représenter efficacement cette classe (mauvaise).

Répondre

18

Si vous n'appelez explicitement aucun constructeur dans la classe de base, le constructeur sans paramètre sera appelé implicitement. Il n'y a pas moyen de contourner cela, vous ne pouvez pas instancier une classe sans qu'un constructeur soit appelé.

+1

En fait, si vous lisez mon commentaire ci-dessous, il y a un moyen, bien que je ne le recommande pas dans la plupart des cas. –

+0

Cette réponse est simplement fausse. Surtout à la lumière de l'autre réponse. – Kobor42

6

Au moins 1 ctor doit être appelé. Le seul moyen de contourner cela, je vois, c'est le confinement. Avoir la classe à l'intérieur ou référencer l'autre classe.

+0

C'est le chemin qui me donne le plus de résultats. Merci! – casademora

1

J'ai peur que le constructeur d'appel de base ne soit pas une option.

1

Lorsque vous créez un objet BaseClassProxy dont il a besoin pour créer une instance de c'est la classe de base, vous devez appeler le constructeur de la classe de base, ce que vous pouvez doo est de choisir wich à appeler, comme:

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

Pour appeler le second constructeur au lieu du premier

4

Je ne crois pas que vous puissiez contourner l'appel du constructeur. Mais vous pourriez faire quelque chose comme ceci:

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

Si ce que vous voulez est de pas appel ou l'autre des deux constructeurs de classe de base, cela ne peut pas être fait.

Les constructeurs de classe C# doivent appeler des constructeurs de classe de base. Si vous n'appelez pas explicitement, base() est implicite. Dans votre exemple, si vous ne spécifiez pas constructeur de la classe de base pour appeler, il est le même que:

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

Si vous préférez utiliser l'autre constructeur de la classe de base, vous pouvez utiliser:

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

Dans les deux cas, l'un des deux sera appelé explicitement ou implicitement.

0

je fini par faire quelque chose comme ceci:

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

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

Cela m'a fait autour de quelques-unes des mauvaises pratiques de la classe de base.

+2

Le constructeur implicite par défaut appelant toujours le constructeur sans paramètre de BaseClass. – recursive

46

Il existe un moyen de créer un objet sans appeler les constructeurs d'instance.

Avant de continuer, soyez très sûr de vouloir faire comme ça. 99% du temps c'est la mauvaise solution.

Voici comment vous le faites:

FormatterServices.GetUninitializedObject(typeof(MyClass)); 

Appel à la place du constructeur de l'objet. Il va créer et vous renvoyer une instance sans appeler les constructeurs ou les initialiseurs de champs.

Lorsque vous désérialisez un objet dans WCF, il utilise cette méthode pour créer l'objet. Lorsque cela se produit, les constructeurs et même les initialiseurs de champ ne sont pas exécutés.

+9

C'est dingue. Mon monde entier est à l'envers! – recursive

+2

Welp, ça a résolu mon problème! Essayer d'éviter les appels de DB du constructeur d'un objet parent lors de l'exécution de tests unitaires sur une classe héritée. – Tarka

+2

FormatterServices.GetUninitializedObject (typeof (MyClass)); appellera toujours les constructeurs statiques, cependant. –

0

Les constructeurs sont publics par nature. n'utilisez pas un constructeur et utilisez-en un autre pour la construction et rendez-le private.so vous créeriez une instance sans paramètre et appelez cette fonction pour construire votre instance d'objet.

0

Ceci est ma première tentative bâclée à cette réponse. Votez et je vais y accorder plus d'attention.

Je ne suis pas sûr de ce que vous essayez d'accomplir, mais il semble que vous manquiez d'interfaces. Vous pouvez choisir quelles interfaces ont du sens pour votre besoin. Si c'est pour tester, vous utiliserez alors quelque chose comme A.Fake pour tester. Si vous fournissez plus de détails sur ce que vous essayez d'accomplir. Je pourrais probablement être plus utile.

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){} 
} 
Questions connexes