2013-02-06 4 views
2

나는 모든 공분산 질문을 실제로 검색했으며 아무 것도 내 문제와 같이 보이지 않습니다.비 일반 클래스의 C# 공분산

나는 사용자 컨트롤 (이 클래스는 분명한 이유를 들어, 일반적인 캔트)를 가지고, 그것은 다음과 같습니다

class MyUserControl : UserControl 
{ 
    private BaseDao<object> _dao; 
    private AppointmentMapping<object> _mapping; 

    // I need these 2 generics to type safe the mapping/dao relation 
    public void RegisterPersistence<T>(BaseDao<T> dao, AppointmentMapping<T> mapping) 
    { 
     // These two dont work. even with safe and unsafe casting. 
     _dao = dao; 
     _mapping = mapping; 
    } 
} 

이미 등 그것을 공분산, 인터페이스에 대한 대리자를 저장하기 위해 노력하고 단지 개체를 저장하지 마십시오! 어떻게해야합니까? 이것은 Java로 쉽게 달성 할 수 있습니다.

+1

이 질문은 'UserControl'과 관련이없는 것으로 보입니다. 모든 수업에서 발생할 수 있습니다. 이 질문을 편집하여 "일반"으로 만들 수 있습니다. –

+0

BaseDao 및 AppointmentMapping의 정의를 알 수는 없지만 실제로 제네릭 클래스 인 경우 제네릭 매개 변수에는 공/대조 변수가 없습니다. in C# – SWeko

+1

요점은 나중에 필드에 액세스하려는 방법을 말하지 않는다는 것입니다. 확실하게 그것들을'object'로 저장하면 효과가 있습니다. 나중에 다른 코드 조각에서 해당 필드에 액세스해야하는 경우 다시 ''이 필요하고 올바른 구현으로 객체로 캐스팅하거나 해당 필드를 대리자 (Action 유형)에 사용하는 코드를 등록 할 수 있습니다. , 예. 나중에 실행하십시오. 그렇지 않으면 BaseDoa와 AppointmentMapping이 비 제네릭 인터페이스를 구현하고이를 필드 유형으로 사용하십시오. – Sebastian

답변

2

다음을 시도해보십시오. 아이디어는 사용 시간에 T를 캡처하여 "나중에 수행 할 작업을 알고있는"클래스에 저장하는 것입니다. 그런 다음 인터페이스를 통해 클래스의 항목을 참조하십시오 (유형 정보는 생략). 나중에 인터페이스를 통해 저장된 값을 호출하십시오. 그렇게하면 특정 인터페이스를 구현하기 위해 일반 클래스를 리팩터링 할 필요가 없습니다.

class MyUserControl : UserControl 
    { 

    // hold a reference to the helper - no generics needed here -> "covariant" 
    private IHelper helper; 

    // I need this 2 generics to type safe the relation between the mapping and the dao 
    public void RegisterPersistence<T>(BaseDao<T> dao, AppointmentMapping<T> mapping) { 
     // "pass <T>" for later usage 
     this.helper = new HelperImpl<T>(dao, mapping); 
    } 

    // use the stored values... 
    public void doStuff() { 
     helper.doStuff(); 
    } 

    // the non generic interface 
    private interface IHelper 
    { 
     void doStuff(); 
    } 

    // a generic implementation for storing the items *and* using them. 
    private sealed class HelperImpl<T> : IHelper 
    { 
     private readonly BaseDao<T> dao; 
     private readonly AppointmentMapping<T> mapping; 

     public HelperImpl(BaseDao<T> dao, AppointmentMapping<T> mapping) { 
     this.dao = dao; 
     this.mapping = mapping; 
     } 

     public void doStuff() { 
     this.dao.foo(); 
     this.mapping.foo(); 
     } 
    } 
    } 
+0

고마워요! 그것을 만든 결과 sweeeeeeeeet입니다. – Stew

+0

이것이 가능하면 원래 개체를 사용자 컨트롤에 직접 저장할 수있는 비 일반베이스로 다시 요소화할 수도 있습니다. –

0

이것은 내가 아는 한 최선의 방법입니다. 세바스찬처럼

은 당신이 할 수있는 것은 공분산 및 contravariance는 인터페이스 필요 사용하려면

class MyUserControl : UserControl 
{ 
    private object _dao; 
    private object _mapping; 

    // I need this 2 generics to type safe the relation between the mapping and the dao 
    public void RegisterPersistence<T>(BaseDao<T> dao, AppointmentMapping<T> mapping) 
    { 
     _dao = dao; 
     _mapping = mapping; 
    } 


    public BaseDao<T> GetDao<T>() 
    { 
     return _dao as BaseDao<T>; 
    } 

    public AppointmentMapping<T> GetAppointmentMapping<T>() 
    { 
     return _mapping as AppointmentMapping<T>; 
    } 
} 
+0

클래스 내부의 객체를 사용하기 때문에 작동하지 않습니다. – Stew

+0

이것은 어렵거나, 말한 것처럼 불가능합니다. 무엇을하고 싶습니까? –

+0

그냥 그 데이터를 유지하기 위해 나중에 UserControl 및 사용자 안에 DAO를 저장하십시오. – Stew

0

H.alex이 옳다, 가장 좋은 것은 다른 레이어에 일반 비트를 이동하는 것 따라서 클래스를 generic으로 만들 수 있고 객체가 아닌 일반적인 클래스 멤버를 가질 수 있습니다. 이 클래스는 제네릭 타입을 추론 할 수 있어야하거나 같은 것을 작성해야 : 새 인스턴스에서 모든 구성원을 매핑 돌봐 가지고 명확 유지 보수가 아니다

public class BaseDao<T> 
{ 
    public T Item { get; set; } 
} 

public class TestClass 
{ 
    private BaseDao<object> _dao; 

    public void RegisterPersistence<T>(BaseDao<T> dao) 
    { 
     _dao = Activator.CreateInstance<BaseDao<object>>(); 
     //need to map each member of BaseDao 
     _dao.Item = dao.Item; 
    }  
} 

합니다.

+0

이것은 공분산이 아니며, 불변량입니다. –

+0

을 true로 캐스트 할 수 없으며 클래스에 제약 조건을 포함 할 필요가있는 공변 인터페이스를 추가하려면 여기를 클릭하십시오. 말한대로 가장 좋은 것은 MyUserControl 클래스 밖에서 일반 부분을 이동하는 것입니다. –