在使用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
}
}
我想要达到的目标绝对简单。我需要在顶级基类中实例化'da'对象。具体类型“UsersDAL”由具体类UserController提供,正确的类型应该传播到应该实例化的顶级基类(BusinessDataController)。
现在,当我调试BusinessDataController时,我可以看到正在传播类型(UsersDAL),在BusinessDataControllerBase()构造函数中创建了一个新的UsersDAL()对象,但是一旦代码从构造函数中传出在BusinessDataControllerBase中,'da'成员变量显示为'null',因此DoLogin()进程da.GetUser()发出错误(对象未实例化)。
但是,如果不是在BusinessDataController中实例化'da',而是在BusinessMasterRootData控制器中创建它(在Level 2,即具体类UserController上方的类),那么一切运行正常并且da.GetUser()作为预期
我试图探索泛型的遗传影响(封闭式构造和开放式构造等),但在我的代码中找不到任何偏差。在设计/编译时,我没有收到任何错误,并且使用IntelliSense获取UsersDAL的所有方法,这可能表明类型用法是正确的。
知道我哪里错了吗?我将在第三级有多个基类,即'BusinessMasterRootDataControllerBase'级别。因此,在第三级实例化'da'将使具体类中的'da'可用,但在该级别的所有类中将是多余的,这就是为什么我要将它('da')置于更高的位置。顺便说一句,如果我将构造函数代码放在第二级(即BusinessRootDataControllerBase),则会发生同样的观察。
要分享的另一个信息是我使用UserController(具体类)作为Singleton类。
感谢任何帮助。
答案 0 :(得分:2)
in
protected BDA da;
public BusinessDataControllerBase()
{
// Initialize the respective Data Access Layer passed by the concrete class
BDA da = new BDA();
}
有两个名为'da'的项目,您正在为一个超出范围的局部变量分配一个新的BDA()。它可能看起来像:
protected BDA da;
public BusinessDataControllerBase()
{
// Initialize the respective Data Access Layer passed by the concrete class
da = new BDA();
}
答案 1 :(得分:0)
也许我只是忽略了这一点,但你应该在你的层次结构中显式调用基类构造函数。
这应该有效:
// 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
}
}