2009-11-06 5 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; } 
     } 
    } 

} 

홈페이지에서 내가 (BL 저장소에 존재) MyBLMethod를 호출하고 (당신이 UI로 생각할 수) 및 클래스 객체를 전달하고 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

캐스팅에서 예외가 발생 했습니까? – strager

+0

예 위의 캐스팅은 " 'TestConsole.MyDTO'"예외에 'TestConsole.DTO'유형의 객체를 형 변환 할 수 없습니다. – Raghav

답변

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 인 경우 추가 속성을 추가 할 수 없습니다. 그런 식으로 일하지 않습니다, 미안 해요.

원하는 것은 개체를 변환하는 것입니다 (어쩌면). 부모 클래스를 가져 와서 모든 내용을 그 자체로 복사 할 수있는 생성자 클래스를 만든 다음 추가 속성을 갖습니다.

+0

나는 당신이 요점을 놓치고 있다고 생각한다. 그는 MyDTO 객체를 포함하는 객체를 BL에 보내지 만, DAL에 보내지는 않는다. – Guffa

+0

반환 형식이 쓰여진 형식과 다르므로 Well D()는 가상 일 수 없습니다. 따라서 올바른 고정 방법이있을 수 있습니다. –

+0

@ Jason : 사실입니다. 그러나 다른 반환 유형은 아무 것도 사용되지 않으므로 동일한 값으로 변경하여 속성을 가상으로 유지할 수 있습니다. – Guffa

1

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 개체를 전달하기 때문입니다. MyBLMethod 메서드는 MyDTO 개체가 있더라도 DTO 개체를 항상 DAL로 보냅니다.

D 속성을 가상으로 설정하지 않았습니다. 즉, A 참조에서 D 속성을 사용하면 실제 객체가 B 인스턴스에 발생해도 A 클래스에 포함 된 DTO 객체를 가져 와서 MyDTO 객체도 갖게됩니다.

참조 유형으로 지정된 객체 대신 실제 객체의 D 속성에 액세스하도록 D 속성을 가상으로 만들 수 있습니다.

또는 당신이 대신의 반대 MyDTO의 액세스 할 수 있도록 B에 대한 참조를 캐스팅 할 수는 DTO 객체의 다음 B 클래스는 DTO와 MyDTO 객체를 모두 포함

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

참고하는 수도 있지 당신이 정말로 원하는 것입니다.

2

정적 비즈니스 로직 방법을 통과하기 때문에 "해상도"가 떨어지는 것처럼 들립니다. 나는 먼저 DAL 방법으로 고투하기보다는 그 부분을 다시 방문 할 것을 제안 할 것이다.

그래야만하는 이유가있을 수 있습니다. 그렇다면 리플렉션을 사용하여 필요한 속성을 찾거나 "as"형변환을 사용하고 dal 메소드에서 null을 테스트하는 방법을 고려해 볼 수 있습니다.이 디자인으로 붙어 있지 않다면 정적 메서드에서 벗어나 리팩터링 할 것입니다. Static은 매우 쉽고 불행하게도 정적 메서드를 나중에 가상 메서드로 쉽게 변경할 수 없음을 상기시키는 것을 잊어 버리는 정적 메서드를 만들기 위해 많은 코드 '품질'도구가 있습니다.