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

时间:2010-10-07 17:58:03

标签: c# design-patterns architecture interface generics

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

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

那么,我的选择是什么?我可以创建 IProgram 界面,并使 StaticProgram DynamicProgram 实现该界面并让我的数据访问类返回 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);
        }
}

这个编译得很好,但我得到了一个不能在运行时将“Program”强制转换为“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
}

当然上面的代码不起作用。我得到“给定的表达式永远不会是提供的类型(StaticProgram)类型。”

4 个答案:

答案 0 :(得分:1)

这个怎么样:

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);
    }
}

哲学上,也许一个界面可能更适合,但是为了以最小的努力获得你必须工作的东西,这应该可以解决问题。

您发布的代码不会转换为DynamicProgram,因为您在ProgramDataMapper中专门构建了一个Program对象。虽然DynamicProgram“是一个”程序,但事实并非如此。在我在这里提供的代码中,使用泛型,构造DynamicProgram而不仅仅是程序。使用泛型也完全不需要在DynamicProgram.GetProgram方法中进行强制转换。

答案 1 :(得分:0)

  

我尝试创建一个“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);
       }
    }

}

答案 2 :(得分:0)

要检查的是你的哪种方法违反LSP(Liskov替代原则)。既然你自己说过它们是两个非常不同的东西,继承模型的使用在这里就无法真正起作用。冗余代码可以被剥离到第三个类,它会通过静态方法暴露自己,或者你可以在你的两个程序对象中引用这个'helper'类。

答案 3 :(得分:0)

如何使用静态类来完成所有DataAccess?