2009-11-06 68 views
3

我有一個BL類,名爲:A,DTO類,名爲:DTO。現在假設我想在我的DTO中添加更多的屬性。所以,我從我現有的DTO派生出新的DTO類,並添加屬性it.Below是代碼:C#多態性問題

namespace TestConsole 
{ 
    class test 
    { 
     static void Main(string[] args) 
     { 

      B b = new B(); 
      b.D.ID = 1; 
      b.D.Name = "4"; 
      MyBLMethod(b); 

     } 
     static void MyBLMethod(A b) 
     { 
      MyDALMethod(b.D); 
     } 

     static void MyDALMethod(DTO dto) 
     { 
      int i = dto.ID; 
      string name = ((MyDTO)dto).Name;//I could not do this 
      //because i will get object cast error as i can't cast from 
      //parent to child 
     } 

    } 
    public class DTO 
    { 
     public int ID = 99; 
     public DTO() 
     { 
     } 

     public DTO(DTO source) 
     { 
      ID = source.ID; 
     } 
    } 

    public class MyDTO : DTO 
    { 
     public string Name = ""; 
     public MyDTO() { } 
     public MyDTO(MyDTO source) 
      : base(source) 
     { 
      Name = source.Name; 

     } 
    } 
    public class A 
    { 
     private DTO _d; 
     public A() 
     { 
      D = new DTO(); 

     } 

     public DTO D 
     { 
      get { return _d; } 
      set { _d = value; } 
     } 
    } 

    public class B : A 
    { 
     private MyDTO _md; 
     public B() 
     { 
      _md = new MyDTO(); 

     } 

     public MyDTO D 
     { 
      get { return _md; } 
      set { _md = value; } 
     } 
    } 

} 

從主(你可以把它作爲UI)我打電話MyBLMethod(存在於BL庫)和將類對象傳遞給它,並從BL存儲庫中調用我的DAL。在DAL我寫了這樣的:

static void MyDALMethod(DTO dto) 
{ 
    int i = dto.ID; 
    string name = ((MyDTO)dto).Name;//I could not do this 
     //because i will get object cast error as i can't cast from 
     //parent to child 
} 

你能否建議我如何得到我的DAL中新擴展的屬性(在這個例子中的名稱)。

+0

你確定cast會拋出異常嗎? – strager 2009-11-06 22:20:46

+0

是的,上面的投射會拋出「無法投射'TestConsole.DTO'類型的對象來鍵入'TestConsole.MyDTO'」異常。 – Raghav 2009-11-06 22:23:39

回答

4

當B繼承A時,它已經擁有一個DTO屬性。所以問題在於你隱藏了這個繼承。您不需要B類中的新屬性,只需在您的類構造函數中進行設置即可。

public class B : A 
    { 
     public B() 
     { 
      this.D = new MyDTO(); 
     } 

    } 

但是,在你的主類,你需要在你的財產一個明確的轉換,就像下面,因爲DTO沒有一個「名稱」屬性。

static void Main(string[] args) 
     { 
      B b = new B(); 
      b.D.ID = 1; 
      ((MyDTO)b.D).Name = "4"; 
      MyBLMethod(b); 
     } 
3

如果對象是基本類型的ACTUALLY,那麼不能直接附加其他屬性。不會那樣工作,對不起。

你想要什麼是CONVERT對象(也許)。在您的子類中創建一個構造函數,它可以接收父項並將其全部內容複製到自身中 - 然後您將擁有其他屬性。

+0

我認爲你錯過了一點......他向BL發送了一個包含MyDTO對象的對象,但未能將其發送到DAL。 – Guffa 2009-11-06 22:36:14

+0

D()不能是虛擬的,因爲返回類型與寫入不同,所以可能有一些有效的方法來修復它。 – 2009-11-06 22:46:29

+0

@Jason:這是真的,但不同的返回類型不用於任何事情,所以它可以更改爲相同的,以便該屬性可以是虛擬的。 – Guffa 2009-11-07 02:51:26

1

允許B通過A a DTO對象在A的構造函數中。如果需要,使構造函數protected。然後,有B.D轉換A.D

public class A 
{ 
    private DTO _d; 

    // New constructor. 
    protected A(DTO d) 
    { 
     _d = d; 
    } 

    // Old constructor calls new constructor. 
    public A() : this(new DTO()) 
    { 
    } 

    public DTO D 
    { 
     get { return _d; } 
     set { _d = value; } 
    } 
} 

public class B : A 
{ 
    // Old B constructor calls new A constructor. 
    public B() : base(new MyDTO()) 
    { 
    } 

    new public MyDTO D 
    { 
     // Getting D casts A.D instead of using an object exclusive to B. 
     get { return (MyDTO)base.D; } 
     set { base.D = value; } 
    } 
} 
3

轉換失敗的原因是您沒有將MyDTO對象傳遞給方法,而是DTO對象。即使存在MyDTO對象,MyBLMethod方法也總是將DTO對象發送到DAL。

您尚未將D屬性設爲虛擬。這意味着,當您在A引用上使用D屬性時,即使實際對象發生在B實例中,也會得到A類包含的DTO對象,以便它也具有MyDTO對象。

您可以使D屬性虛擬爲訪問實際對象的D屬性,而不是引用類型指定的屬性。

或者你可以投的參考到B,這樣就可以訪問它的MyDTO對象,而不是它的DTO對象:

static void MyBLMethod(A b) { 
    MyDALMethod(((B)b).D); 
} 

注意,B級包含一個DTO和MyDTO對象,這可能不是成爲你真正想要的東西。

2

這聽起來像你正在失去「決議」,因爲你正在通過一個靜態的業務邏輯方法。我建議重新審視那部分,而不是先用DAL方法掙扎。

雖然可能有一個原因,但如果是這樣的話,可以考慮使用反射來查找所需的屬性或使用「as」投射,然後在您的dal方法中測試null。如果你沒有使用這個設計,我會重構靜態方法。靜態看起來很簡單,不幸的是有很多代碼的「質量」工具促使你使方法變爲靜態,忘記提醒你以後不能輕易地將靜態方法改爲虛擬方法。