接口,抽象还是继承?C#设计问题
我有一个包含两个实体的表,静态程序和动态程序。该表中有一列称为ProgramType,用于确定程序的类型是“静态”还是“动态”。虽然这两个实体存储在一个表中(我猜是因为静态和动态程序的基本字段完全相同),但从业务角度来看,这两个实体是非常不同的 因此,我创建了两个类StaticProgram和DynamicProgram。但是,我不想创建两个独立的数据访问类,因为它将是完全相同的代码复制两次。我尝试创建一个“Program”类作为基类和继承的StaticProgram和DynamicProgram类,但不支持向下转换,因此无法从数据访问类返回“Program”对象并将其转换为“StaticProgram”类等 那么,我的选择是什么?我是否可以创建一个IProgram接口,并让静态程序和动态程序实现该接口,并让我的数据访问类返回IProgram?或者让数据访问方法成为泛型方法如何(如果这是可能的并且是推荐的方法,我需要一些帮助,因为我对泛型没有太多经验)?还有其他建议吗 谢谢你的帮助 更新: 数据访问方法实际上是静态的:接口,抽象还是继承?C#设计问题,c#,design-patterns,architecture,interface,generics,C#,Design Patterns,Architecture,Interface,Generics,我有一个包含两个实体的表,静态程序和动态程序。该表中有一列称为ProgramType,用于确定程序的类型是“静态”还是“动态”。虽然这两个实体存储在一个表中(我猜是因为静态和动态程序的基本字段完全相同),但从业务角度来看,这两个实体是非常不同的 因此,我创建了两个类StaticProgram和DynamicProgram。但是,我不想创建两个独立的数据访问类,因为它将是完全相同的代码复制两次。我尝试创建一个“Program”类作为基类和继承的StaticProgram和DynamicProgra
public static class ProgramDataMapper
{
public static Program GetProgram(int programID)
{
Program p = new Program();
// database stuff
p.Name = reader["Name"].ToString();
...
return p;
}
}
基类看起来像:
public class Program
{
// Properties
public static Program GetProgram(int programID)
{
return ProgramDataMapper.GetProgram(programID);
}
}
最后,派生类:
public class DynamicProgram : Program
{
// Additional Business Related Properties
public new static DynamicProgram GetProgram(int programID)
{
return (DynamicProgram)Program.GetProgram(programID);
}
}
这可以很好地编译,但我在运行时遇到了无法将“程序”强制转换为“DynamicProgram”的异常
还有,通用方法呢?除非我在这里偏离了主题,但从理论上讲,我们不能这样做:
public static IProgram GetProgram<T>(int programID) where T : IProgram
{
IProgram program;
Type returnType = typeof(T);
if(returnType is StaticProgram)
{
program = new StaticProgram();
}
else if(returnType = DynamicProgram)
{
program = new DynamicProgram();
}
//if (T is StaticProgram)
//{
// returnValue = new StaticProgram();
//}
//else if (T is DynamicProgram)
//{
// returnValue = new DynamicProgram();
//}
// db operations
}
publicstaticiprogram GetProgram(int-programID),其中T:IProgram
{
IProgram程序;
类型returnType=类型(T);
if(返回类型为StaticProgram)
{
程序=新的静态程序();
}
else if(返回类型=动态程序)
{
程序=新的动态程序();
}
//if(T是静态程序)
//{
//returnValue=新的StaticProgram();
//}
//else if(T为动态程序)
//{
//returnValue=新的DynamicProgram();
//}
//数据库操作
}
当然,上面的代码不起作用。我得到“给定的表达式永远不是提供的类型(StaticProgram)类型。”
我尝试创建一个“Program”类作为基类和继承的StaticProgram和DynamicProgram类,但不支持向下转换,因此无法从数据访问类返回“Program”对象并将其转换为“StaticProgram”类等
很奇怪,因为这应该是可行的:
public Program GetProgram(){
if(someDataCoulumn.Equals("Static")) {
return new StaticProgram(...);
} else {
return new DynamicProgram(...);
}
}
public void Caller(){
var p = GetProgram();
var sp = p as StaticProgram;
if(sp != null) {
DoSomethingWithStaticProgram(sp);
} else {
var dp = p as DynamicProgram;
if(dp != null){
DoSomethingWithDynamicProgram(dp);
} else {
throw new SomeBusinessException("Program is neither Static not Dynamic, instead it's " + p.GetType().FullName);
}
}
}
要检查的是,哪种方法不违反LSP(Liskov替换原则)。因为您自己说过,它们是两件完全不同的事情,所以在这里使用继承模型并不能真正起作用。多余的代码可以剥离到第三个类中,通过静态方法暴露自己,或者您可以在两个程序对象中的每个对象中引用此“helper”类。让一个静态类来完成所有数据访问怎么样?这样如何:
public static class ProgramDataMapper
{
// Change to a generic here to manufacture any class deriving from Program.
public static T GetProgram<T>(int programID)
where T : Program, new()
{
T p = new T();
// database stuff
p.Name = reader["Name"].ToString();
...
return p;
}
}
public abstract class Program
{
// Properties
// Manufacture a concrete class that derives from Program
public new static T GetProgram<T>(int programID)
where T : Program, new()
{
return ProgramDataMapper.GetProgram<T>(programID);
}
}
public class DynamicProgram : Program
{
// Additional Business Related Properties
public new static DynamicProgram GetProgram(int programID)
{
// Specifically manufacture a DynamicProgram
return Program.GetProgram<DynamicProgram>(programID);
}
}
公共静态类ProgramDataMapper
{
//此处更改为泛型,以生成从程序派生的任何类。
公共静态T GetProgram(int programID)
其中T:Program,new()
{
tp=新的T();
//数据库材料
p、 Name=reader[“Name”].ToString();
...
返回p;
}
}
公共抽象类程序
{
//性质
//制造从程序派生的具体类
公共新静态T GetProgram(int programID)
其中T:Program,new()
{
返回ProgramDataMapper.GetProgram(programID);
}
}
公共类动态程序:程序
{
//其他与业务相关的财产
公共新静态动态程序GetProgram(int programID)
{
//专门制作一个动态程序
返回程序.GetProgram(programID);
}
}
从理论上讲,接口可能更合适,但对于以最小的努力获得所需的工作,这应该可以做到
您发布的代码不会强制转换为DynamicProgram,因为您在ProgramDataMapper中专门构造了一个程序对象。虽然DynamicProgram“是”程序,但事实并非如此。在我这里提供的代码中,使用泛型构造了一个DynamicProgram,而不仅仅是一个程序。使用泛型还完全不需要在DynamicProgram.GetProgram方法中强制转换。答案可能会因您使用的ORM(如NHibernate或Linq2SQL)而大不相同。。。你能指定你使用的是什么ORM吗?我没有使用任何ORM,比如说,我是手动创建mapper类的。我们正在调查实体框架,但到目前为止还没有定案:(这正是我想要的!非常感谢!