通用继承问题(开放构造)

时间:2021-11-09 23:00:58

I am facing this strange problem while working with Generic Base Classes. I am having three levels of base class hierarchy while the fourth level is the concrete class. Something as below.

在使用Generic Base Classes时,我遇到了这个奇怪的问题。我有三个级别的基类层次结构,而第四个级别是具体类。如下所示。

// 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
        }
}

What I want to achieve is absolute simple. I need the 'da' object to be instantiated at the top level base class. The concrete type 'UsersDAL' is supplied by the concrete class UserController and the correct type should be propagated till the top level base class (BusinessDataController) where it should be instantiated.

我想要实现的是绝对简单。我需要在*基类中实例化'da'对象。具体类型“UsersDAL”由具体类UserController提供,并且应该传播正确的类型,直到应该实例化它的*基类(BusinessDataController)。

Now while I am debugging the BusinessDataController, I can see that the type (UsersDAL) is being propagated, a new UsersDAL() object is getting created in BusinessDataControllerBase() constructor but as soon as the code is coming out of the constructor in BusinessDataControllerBase, the 'da' member variables shows as 'null' and hence the DoLogin() process da.GetUser() is giving an error (object not instantiated).

现在,当我调试BusinessDataController时,我可以看到正在传播类型(UsersDAL),在BusinessDataControllerBase()构造函数中创建了一个新的UsersDAL()对象,但是一旦代码从BusinessDataControllerBase中的构造函数出来, 'da'成员变量显示为'null',因此DoLogin()进程da.GetUser()发出错误(对象未实例化)。

But, if instead of instantiating 'da' in BusinessDataController, I create it in BusinessMasterRootData controller (at Level 2, i.e. the class just above the concrete class UserController), then everything is running fine and da.GetUser() works as expected.

但是,如果不是在BusinessDataController中实例化'da',而是在BusinessMasterRootData控制器中创建它(在Level 2,即具体类UserController上方的类),那么一切正常,da.GetUser()按预期工作。

I have tried to explore inheritance impacts of Generics (closed construction and open construction etc.) but could not find any deviations in my code. In design/compile time, I am not getting any error and getting all methods of UsersDAL with IntelliSense which possibly indicates that the type usage is correct.

我试图探索泛型的遗传影响(封闭式构造和开放式构造等),但在我的代码中找不到任何偏差。在设计/编译时,我没有收到任何错误,并且使用IntelliSense获取UsersDAL的所有方法,这可能表明类型使用是正确的。

Any idea where am I going wrong? I will have multiple base classes at the third level, i.e. the 'BusinessMasterRootDataControllerBase' level. So instantiating 'da' at the third level will make 'da' available in the concrete classes but will be redundant in all classes at that level and that is why I want to place it ('da') higher up. By the way, same observation is happening if I place the constructor code at the second level (i.e. BusinessRootDataControllerBase).

知道我哪里错了吗?我将在第三级有多个基类,即'BusinessMasterRootDataControllerBase'级别。因此,在第三级实例化'da'将使具体类中的'da'可用,但在该级别的所有类中将是多余的,这就是为什么我要将它('da')置于更高的位置。顺便说一句,如果我将构造函数代码放在第二级(即BusinessRootDataControllerBase),则会发生同样的观察。

Another information to share is I am using the UserController (concrete class) as a Singleton class.

另一个要分享的信息是我使用UserController(具体类)作为Singleton类。

Any help is appreciated.

任何帮助表示赞赏。

2 个解决方案

#1


in

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

There are two items named 'da', you are assigning a new BDA() to a local variable that goes out of scope immediately. It probably should look like:

有两个名为'da'的项目,您正在为一个超出范围的局部变量分配一个新的BDA()。它可能看起来像:

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

#2


Maybe I'm just missing the point, but you should explicitly call the base class constructors in your hierarchy.

也许我只是忽略了这一点,但你应该在层次结构中显式调用基类构造函数。

This should work:

这应该工作:

// 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
   } 
}

#1


in

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

There are two items named 'da', you are assigning a new BDA() to a local variable that goes out of scope immediately. It probably should look like:

有两个名为'da'的项目,您正在为一个超出范围的局部变量分配一个新的BDA()。它可能看起来像:

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

#2


Maybe I'm just missing the point, but you should explicitly call the base class constructors in your hierarchy.

也许我只是忽略了这一点,但你应该在层次结构中显式调用基类构造函数。

This should work:

这应该工作:

// 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
   } 
}