generics를 사용하여 공장/빌더를 제공하여 인터페이스 구현을 추상화하려고합니다. 그러나, 나는 여러 디스패치와 실행 시간에 C# generics와 관련하여 이상하게 보이는 것을 실행하는 문제에 직면하고 있습니다.Generics를 사용한 다중 발송
기본 시나리오는 내가 정의한되는 여러 인터페이스 :
public class Factory
{
public T BuildModel<T>()
{
return BuildModel(default(T));
}
public object BuildModel(object obj)
{
//this is here because the compiler will complain about casting T to
//the first inteface parameter in the first defined BuildModel method
return null;
}
public IAddressModel BuildModel(IAddressModel iModel)
{
//where AddressModel inherits from IAddressModel
return new AddressModel();
}
public IUserModel BuildModel(IUserModel iModel)
{
//where UserModel inherits from IUserModel
return new UserModel();
}
}
이 문제는 공장처럼
라고되어public interface IAddressModel
{
}
public interface IUserModel
{
}
은 그럼 실제 구현을 반환하는 공장 클래스가 this : new Factory().BuildModel<IAddressModel>()
generics에서 런타임에 전달되는 BuildModel (...) 메서드는 항상 T의 최소 파생 형식이며,이 경우 항상 개체입니다.
그러나 new Factory().BuildModel(default(IAddressModel));
을 호출하면 올바른 방법이 대체됩니다 (대부분 컴파일 타임에 수행되기 때문일 수 있습니다). 제네릭을 사용한 동적 디스패치는 호출 된 메서드가 컴파일 타임이나 런타임에 완료 되든 같아야 할지라도 가장 많이 파생 된 메서드의 메서드를 확인하지 않는 것으로 보입니다. 이상적으로 BuildModel (...) 메서드를 private으로 만들고 일반 메서드 만 노출하고 싶습니다. 동적 메서드를 사용하여 런타임에 올바른 메서드를 호출하는 다른 방법이 있습니까? 구현을 return BuildModel((dynamic)default(T))
으로 변경하려고 시도했지만 디스패치 할 메소드를 결정할 수 없다는 런타임 오류가 발생합니다. contravariance와 더 많은 인터페이스로 이것을 할 수있는 방법이 있을까요?
은 당신이 생각 해 봤나'새 공장 < IAddressModel>(). BuildModel()'대신에? – Bobson
@Bobson - 네, 제네릭을 메서드 수준 대신 클래스 수준으로 옮겨 보았습니다. 런타임 디스패치와 아무런 차이가 없습니다. – SignalRichard
이것이 실행 시간 대 컴파일 시간 문제라고 생각하지 않습니다. 필자가 아는 한,'dynamic'을 사용하지 않는다면 일반 타입과 마찬가지로 컴파일시에 제네릭이 모두 해결됩니다. 그리고'default (T)'가'null '이 될 것이기 때문에 당신은'dynamic'을 사용할 수 없기 때문에 그것이 무엇인지를 결정할 수 없습니다. 나는 이것이 공장의 표준이 '스위치'를 사용하는 이유 중 일부라고 생각한다. – Bobson