2010-10-07 69 views
0

我有一个表,其中包含两个实体,StaticProgramDynamicProgram。该表中有一列称为ProgramType,用于确定程序是“静态”还是“动态”类型。虽然这两个实体存储在一个表中(我猜测是因为静态和动态程序的原始字段完全相同),但从业务角度来看,这些实体是两个非常不同的实体。界面,抽象还是继承? C#设计问题

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

那么,我有什么选择?我可以创建一个IProgram接口,并有StaticProgramDynamicProgram实现该接口,并有我的数据访问类返回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); 
     } 
} 

这编译很好,但我得到一个Cann在运行时不会将“程序”强制转换为“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)类型。”

+0

答案可能会有很大的不同,取决于你使用的是什么ORM,比如NHibernate或者Linq2SQL等等......你能指定你使用的ORM吗? – code4life 2010-10-07 18:50:05

+0

我没有使用任何ORM,我手动构建了mapper类。我们正在调查实体框架,但到目前为止没有最后确定: – Robert 2010-10-07 20:32:56

回答

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方法中完全消除需要投射的情况。

+0

这正是我之后!非常感谢你! – Robert 2010-10-07 22:35:28

+0

@Robert - 很高兴提供帮助。 – 2010-10-08 15:51:37

0

我试图创建一个“程序”类作为基类,并继承StaticProgram和DynamicProgram类,但下降不支持铸造,所以我不能从数据访问类返回一个“程序”对象,并将其转换为“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); 
     } 
    } 

} 
0

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

0

如何让静态类来完成所有的DataAccess?