Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/design-patterns/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
接口,抽象还是继承?C#设计问题_C#_Design Patterns_Architecture_Interface_Generics - Fatal编程技术网

接口,抽象还是继承?C#设计问题

接口,抽象还是继承?C#设计问题,c#,design-patterns,architecture,interface,generics,C#,Design Patterns,Architecture,Interface,Generics,我有一个包含两个实体的表,静态程序和动态程序。该表中有一列称为ProgramType,用于确定程序的类型是“静态”还是“动态”。虽然这两个实体存储在一个表中(我猜是因为静态和动态程序的基本字段完全相同),但从业务角度来看,这两个实体是非常不同的 因此,我创建了两个类StaticProgram和DynamicProgram。但是,我不想创建两个独立的数据访问类,因为它将是完全相同的代码复制两次。我尝试创建一个“Program”类作为基类和继承的StaticProgram和DynamicProgra

我有一个包含两个实体的表,静态程序动态程序。该表中有一列称为ProgramType,用于确定程序的类型是“静态”还是“动态”。虽然这两个实体存储在一个表中(我猜是因为静态和动态程序的基本字段完全相同),但从业务角度来看,这两个实体是非常不同的

因此,我创建了两个类StaticProgramDynamicProgram。但是,我不想创建两个独立的数据访问类,因为它将是完全相同的代码复制两次。我尝试创建一个“Program”类作为基类和继承的StaticProgram和DynamicProgram类,但不支持向下转换,因此无法从数据访问类返回“Program”对象并将其转换为“StaticProgram”类等

那么,我的选择是什么?我是否可以创建一个IProgram接口,并让静态程序动态程序实现该接口,并让我的数据访问类返回IProgram?或者让数据访问方法成为泛型方法如何(如果这是可能的并且是推荐的方法,我需要一些帮助,因为我对泛型没有太多经验)?还有其他建议吗

谢谢你的帮助

更新: 数据访问方法实际上是静态的:

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类的。我们正在调查实体框架,但到目前为止还没有定案:(这正是我想要的!非常感谢!