2010-10-07 67 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?