2013-05-02 2 views
1

그래서 두 개의 다른 네임 스페이스에 대해 클래스 레코드가 있습니다. 나는 전달하려고하는 타입에 기반을 둔 적절한 것을 돌려주고 싶다. 이것을 시도하기 위해, 나는 이것을 시도했지만, "T2"는 올바르지 않다. 이것을 어떻게 할 수 있습니까?하나의 제네릭 형식 매개 변수, 반환 형식에 대해 다른 일반?

public T2 GetGeneratedType<T1>(string name) where T1 : class where T2 : class 
{ 
    var type = typeof(T1); 
    var generatedName = type.AssemblyQualifiedName.Replace(type.Name, name); 
    return (T2)Activator.CreateInstance(Type.GetType(generatedName)); 
} 

나는이 (분명히, 컴파일되지 않습니다) 테스트를하지 않은,하지만 내가 어떻게이 일을해야합니까 그래서에서 Namespace1.SomeClass를 전달하면, 나는 Namespace1.Record을 얻을 경우 내가 통과 것을 Namespace2.SomeOtherClass에서 Namespace2.Record를 얻습니다 (name == "Record"만큼 오래).

처음에는 모든 항목에 대해 T를 시도했지만 오류 메시지를 표시하지는 않았지만 입력 및 출력 유형이 다른 유형으로되어 있는지 확인하려고합니다.

편집 :

전적으로 설명하지는 않았습니까?

포크 레코드에 대한 데이터 주석을 작성 중입니다. (기술적으로 3 명의 독자적인 프로세스가 수행되기 때문에 3 명이이 레코드를 지정할 수 있어야합니다. 프로세스가 완료됩니다. 따라서 namespace1은 하나의 프로젝트이고 (Visual Studio의 의미는 아닙니다) namespace2는 또 다른 프로젝트입니다. 네임 스페이스 1에는 ImportedRecord1이 있고 네임 스페이스 2에 ImportedRecord2가 있습니다 (둘 다 별도의 속성을 가진 별도의 프로젝트이지만 다소간 동일한 목적을 제공함). Namespace1과 Namespace2는 모두 해당 네임 스페이스에 대한 ImportedRecord와 관련된 레코드 유형을 가지며,이 레코드 유형은 다른 유형의 3 "하위 레코드"로 분기됩니다 (기본적으로 해당 프로젝트의 가져온 레코드이지만 3 개의 프로세스 중 하나와 관련된 필드가 있음)).

+0

그래서 컴파일러가 메서드가 런타임에 수행하는 작업을 기반으로 메서드의 반환 형식을 파악하기를 원하십니까? 나는 그것이 불가능하다는 것에 두려워합니다. – svick

+0

그래서 Namespace1.ImportedRecord1을 일반 문자열로 전달하고 "Record"문자열을 전달하고 새로운 Namespace1.Record를 반환 할 방법이 없습니까? 그것은 파업이지만, 나는 머리를 고맙게 생각합니다. – Robert

+0

컴파일 시간 유형은? 반환 된 객체의 런타임 유형은? 예. – svick

답변

2

반환 유형을 T2 대신 동적으로 설정하면됩니다. 유형은 런타임에 결정됩니다.

4

제네릭 메서드 서명의 일부로 두 번째 형식 만 선언하면됩니다.

public T2 GetGeneratedType<T1, T2>(string name) where T1 : class where T2 : class 
{ 
    var type = typeof(T1); 
    var generatedName = type.AssemblyQualifiedName.Replace(type.Name, name); 
    return (T2)Activator.CreateInstance(Type.GetType(generatedName)); 
} 

편집 :

이 정말 귀하의 질문에 직접 관련되지 않는하지만 어쨌든에 발생합니다. 나는 ...이 디자인은 정말 그렇지 않으면 당신에게 값 코드 감소를 주거나 있다고 생각하지 않습니다

  • 당신이 공장은 단순히 지금 당신이 object 유형을 반환하기 때문에 때와 수도처럼 당신은 클래스 디커플링되지 않습니다

    당신은 상대방에게 던지라고 강요 당할 것입니다.

  • 런타임시 리플렉션 리버베이션에서 약간의 성능 저하가 발생하여 이러한 오브젝트가 생성됩니다.

  • 이 특정 시나리오에 대한 일회용 기능 만 수행하면 이러한 관행이 지속될 경우 끈적 거리는 코드로 이어질 수 있습니다.

+0

오직 문제는 런타임까지 어떤 T2가 될지 잘 모르겠다는 것입니다. 나는이 질문에 대한 답변을 찾은 것 같아요 http://stackoverflow.com/questions/11107170/property-type-as-generic-parameter?rq=1. 분명히 물건을 돌려주는 것만 큼 쉽습니다. – Robert

+0

@Robert 클래스의 이름을 전달할 때의 값은 무엇이며 몇 줄의 코드로 객체를 생성해야합니까?이 메소드 호출이 시작된 클래스에서 다시 하드 캐스팅 한 경우 어떻게됩니까? 당신은 그냥 앞으로 단단한 커플 링 = D –

+0

@ 로버트보다는 오히려 난독 화 커플 링으로 붙어있다이 방법을 소개하는 주 목표는 무엇입니까? –

1

일반 유형 매개 변수는 "into"함수 호출로만 이동할 수 있습니다. 함수가 일반적인 반환 값을 가질 수는 있지만 호출자가 반환 값의 형식을 제공해야합니다. [물론 어떤 클래스 유형 T을 반환하는 함수가 인스턴스에 대한 참조를 반환 할 수도 있습니다 T에서 파생 된 모든 유형의 호출자가 반환 값의 유형을 T으로 계속 표시합니다.] 대부분의 경우, 호출자가 형식을 더 정확하게 알고 있거나 결정할 수있는 경우 다소 구체적인 반환 형식을 지정하지 않고 호출자에게이를 캐스트 할 수 있지만이 방법에는 몇 가지 제한이 있습니다. 예를 들어, 반환 된 객체는 독립 제약 인 IFooIBar을 만족하는 형태가 될 수 있지만 반환 될 수있는 유형은 IFooIBar을 구현하는 공통 상위 유형을 공유하지 못할 수 있습니다. IFooIBar 제약 조건을 모두 만족하는 메서드가 반환 값을 전달할 수있는 좋은 신원 보존 방법은 없습니다. 가능한 모든 값을 캐스팅 할 수있는 단일 유형이 없기 때문입니다.

이 제한 사항을 해결하기위한 한 가지 방법은 개체를 호출자에게 반환하지 않고 개체를 호출자가 제공 한 개체의 제네릭 메서드에 전달하는 것입니다. 예를 들어,이 인터페이스를 정의하는 경우 : IFooBarFeeder을 구현하는 클래스가 만족 IFooIBar 알고 물체가있는 경우

interface IFooBarConsumer { PerformAction <T>(T thing) where T:IFoo,IBar; } 
interface IFooBarFeeder { FeedItem(IFooBarConsumer theConsumer); } 

를 그 해당 객체를 전달할 수있는 - 통과에 IFooBarConsumer, 그 소비자에서와 것 방향을 바꾸어 IFooIBar 제약이있는 메소드로 전달할 수 있습니다. 소비자에게 단순히 객체를받는 것이 아니라 코드를 제공하는 것은 어색 할 수 있지만 그렇지 않으면 불가능한 형식 안전한 방식으로 몇 가지 작업을 수행 할 수 있습니다.

관련 문제