2009-06-13 6 views
0

Je suis confronté à ce problème étrange tout en travaillant avec des classes de base génériques. J'ai trois niveaux de hiérarchie de classe de base tandis que le quatrième niveau est la classe concrète. Quelque chose comme ci-dessous.Problème avec l'héritage générique (construction ouverte)

// Level 0 (Root Base Class)  
public abstract class BusinessDataControllerBase<BDA> : IBusinessDataController 
{ 
    protected BDA da; 
    public BusinessDataControllerBase() 
    { 
    // Initialize the respective Data Access Layer passed by the concrete class 
    BDA da = new BDA(); 
    } 
} 


// Level 1 (Second Level Base Class) 
public abstract class BusinessRootDataControllerBase<BDA> : BusinessDataControllerBase<BDA>, IBusinessRootDataController 
     where BDA : IBusinessDALController, new() 
{ 
} 

// Level 2 (Third Level Base Class) 
public abstract class BusinessMasterRootDataControllerBase<BRC, BRD, BDA> : BusinessRootDataControllerBase<BDA>, IDisposable 
     where BRC : IBusinessRootDataController 
     where BRD : IBusinessRootData 
     where BDA : IBusinessDALController, new() 
{ 
} 

// Level 3 (Concrete Class) 
public class UserController : BusinessMasterRootDataControllerBase<UserController, UserData, UsersDAL> 
{ 
     # region Singleton implementation - Private Constructor, Static initialization 
     private static readonly UserController instance = new UserController(); 
     public static UserController Instance 
     { 
      get { return instance; } 
     } 
     # endregion 

     # region Constructor 
     // -------------------------------------------------------------------------------- 
     //Private Constuctor 
     private UserController() 
     { 
     } 
     // -------------------------------------------------------------------------------- 

     private void DoLogin(string userName, string password) 
     { 
      DataSet dstUser = da.GetUser(userName); 
      // Check user name 
      // Check password 
     } 
} 

Ce que je veux accomplir est absolu simple. J'ai besoin que l'objet 'da' soit instancié dans la classe de base de premier niveau. Le type concret 'UsersDAL' est fourni par la classe concrète UserController et le type correct doit être propagé jusqu'à la classe de base de niveau supérieur (BusinessDataController) où il doit être instancié.

Maintenant que je débogue le BusinessDataController, je peux voir que le type (UsersDAL) est propagé, un nouvel objet UsersDAL() est créé dans le constructeur BusinessDataControllerBase() mais dès que le code sort du constructeur dans BusinessDataControllerBase, les variables membres 'da' apparaissent comme 'null' et donc le processus DoLogin() da.GetUser() donne une erreur (objet non instancié). Mais, si au lieu d'instancier 'da' dans BusinessDataController, je le crée dans le contrôleur BusinessMasterRootData (au niveau 2, c'est-à-dire la classe juste au-dessus de la classe concrète UserController), tout fonctionne correctement et da.GetUser() fonctionne comme prévu.

J'ai essayé d'explorer les impacts sur l'héritage des génériques (construction fermée et construction ouverte, etc.) mais je n'ai trouvé aucune déviation dans mon code. En conception/compilation, je ne reçois aucune erreur et j'obtiens toutes les méthodes de UsersDAL avec IntelliSense qui indiquent peut-être que l'utilisation du type est correcte.

Une idée où je vais mal? Je vais avoir plusieurs classes de base au troisième niveau, c'est-à-dire le niveau 'BusinessMasterRootDataControllerBase'. Donc instancier 'da' au troisième niveau rendra 'da' disponible dans les classes concrètes mais sera redondant dans toutes les classes à ce niveau et c'est pourquoi je veux le placer ('da') plus haut. En passant, la même observation se produit si je place le code du constructeur au deuxième niveau (c'est-à-dire BusinessRootDataControllerBase).

Une autre information à partager est que j'utilise UserController (classe concrète) comme une classe Singleton.

Toute aide est appréciée.

Répondre

2

dans

protected BDA da; 
public BusinessDataControllerBase() 
{ 
    // Initialize the respective Data Access Layer passed by the concrete class 
    BDA da = new BDA(); 
} 

Il y a deux éléments nommés « da », vous assignez une nouvelle BDA() à une variable locale qui est hors de portée immédiatement. Il devrait probablement ressembler à:

protected BDA da; 
public BusinessDataControllerBase() 
{ 
    // Initialize the respective Data Access Layer passed by the concrete class 
    da = new BDA(); 
} 
+0

Merci ami. C'était idiot d'avoir raté ça. Il m'a fallu 4 heures de recherche stupide sans résultat. Excellente observation. – Rajarshi

0

Peut-être que je suis manque juste le point, mais vous devez appeler explicitement les constructeurs de classe de base dans la hiérarchie.

Cela devrait fonctionner:

// Level 0 (Root Base Class)  
public abstract class BusinessDataControllerBase<BDA> : IBusinessDataController 
{ 
    protected BDA da; 

    public BusinessDataControllerBase() 
    { 
     // Initialize the respective Data Access Layer passed by the concrete class 
     this.da = new BDA(); 
    } 
}   

// Level 1 (Second Level Base Class) public abstract class 
BusinessRootDataControllerBase<BDA> : BusinessDataControllerBase<BDA>, IBusinessRootDataController 
        where BDA : IBusinessDALController, new() 
{ 
    public BusinessRootDataControllerBase() 
     : base() {}  
} 

// Level 2 (Third Level Base Class) public abstract class BusinessMasterRootDataControllerBase<BRC, BRD, BDA> : BusinessRootDataControllerBase<BDA>, IDisposable 
     where BRC : IBusinessRootDataController 
     where BRD : IBusinessRootData 
     where BDA : IBusinessDALController, new() 
{ 
    public BusinessMasterRootDataControllerBase() 
     : base() {} 
} 

// Level 3 (Concrete Class) public class UserController : BusinessMasterRootDataControllerBase<UserController, UserData, UsersDAL> 
{ 
    # region Singleton implementation - Private Constructor, Static initialization 
    private static readonly UserController instance = new UserController(); 

    public static UserController Instance 
    { 
     get { return instance; } 
    } 
    # endregion 

    # region Constructor 
    // -------------------------------------------------------------------------------- 
    //Private Constuctor 
    private UserController() 
     : base() 
    { 
    } 
    // -------------------------------------------------------------------------------- 

    private void DoLogin(string userName, string password) 
    { 
     DataSet dstUser = da.GetUser(userName); 
     // Check user name 
     // Check password 
    } 
} 
+0

Tant qu'il n'y a pas de paramètres, vous n'avez pas besoin de les appeler explicitement. Le compilateur va insérer: base() –

Questions connexes