저는 컴파일러와 제네릭을 사용하여 런타임 확인을 저장하는 데있어 행운이라고 생각합니다. 이미 존재하지 않는 무언가를 재정의 할 수 없으며 동일한 메소드에 다른 반환 유형을 사용할 수 없습니다.
나는 당신의 동기를 완전히 이해한다고 말할 수는 없지만 기술적 인 장점이 있습니다.
첫 번째 시도는 가상이 아닌 공용 인터페이스가있는 기본 클래스를 사용하고 기본 클래스 Create가 호출되기 전에 체인의 모든 항목에서 유형을 검사 할 수있는 보호 된 가상 메서드 CheckCreatedType
을 사용했습니다.
public class A
{
public IFieldSimpleItem Create()
{
IFieldSimpleItem created = InternalCreate();
CheckCreatedType(created);
return created;
}
protected virtual IFieldSimpleItem InternalCreate()
{
return new SimpleImpl();
}
protected virtual void CheckCreatedType(IFieldSimpleItem item)
{
// base class doesn't care. compiler guarantees IFieldSimpleItem
}
}
public class B : A
{
protected override IFieldSimpleItem InternalCreate()
{
// does not call base class.
return new NormalImpl();
}
protected override void CheckCreatedType(IFieldSimpleItem item)
{
base.CheckCreatedType(item);
if (!(item is IFieldNormalItem))
throw new Exception("I need a normal item.");
}
}
다음은 기본 클래스의 런타임 검사에서 달라 붙습니다.해결할 수없는 문제는 여전히 호출되는 기본 클래스 메서드에 의존해야한다는 것입니다. 오작동하는 하위 클래스는 base.CheckCreatedType(item)
을 호출하지 않고 모든 검사를 중단 할 수 있습니다.
기본 클래스 안의 모든 하위 클래스에 대한 검사를 모두 하드 코딩하거나 (불량) 다른 방법으로 검사를 외부화합니다.
시도 2 : (하위) 클래스는 필요한 수표를 등록합니다.
public class A
{
public IFieldSimpleItem Create()
{
IFieldSimpleItem created = InternalCreate();
CheckCreatedType(created);
return created;
}
protected virtual IFieldSimpleItem InternalCreate()
{
return new SimpleImpl();
}
private void CheckCreatedType(IFieldSimpleItem item)
{
Type inspect = this.GetType();
bool keepgoing = true;
while (keepgoing)
{
string name = inspect.FullName;
if (CheckDelegateMethods.ContainsKey(name))
{
var checkDelegate = CheckDelegateMethods[name];
if (!checkDelegate(item))
throw new Exception("failed check");
}
if (inspect == typeof(A))
{
keepgoing = false;
}
else
{
inspect = inspect.BaseType;
}
}
}
private static Dictionary<string,Func<IFieldSimpleItem,bool>> CheckDelegateMethods = new Dictionary<string,Func<IFieldSimpleItem,bool>>();
protected static void RegisterCheckOnType(string name, Func<IFieldSimpleItem,bool> checkMethod)
{
CheckDelegateMethods.Add(name, checkMethod);
}
}
public class B : A
{
static B()
{
RegisterCheckOnType(typeof(B).FullName, o => o is IFieldNormalItem);
}
protected override IFieldSimpleItem InternalCreate()
{
// does not call base class.
return new NormalImpl();
}
}
체크는 기본 클래스에서 호출 할 대리자를 등록하는 서브 클래스에 의해 수행하지만, 선행 모든 규칙을 알고있는 기본 클래스하지 않고있다. 비 - 가상 공용 인터페이스이기 때문에 기본 클래스가 결과를 반환하기 전에 검사 할 수 있습니다.
나는 당신이 잡으려고하는 개발자 오류라고 가정하고 있습니다. 해당되는 경우 런타임 검사 방법을 System.Diagnostics.Conditional("DEBUG")]
으로 장식하여 릴리스 버전에서 검사를 건너 뛸 수 있습니다.
제네릭에 대한 지식이 완벽하지 않으므로 필요하지 않을 수 있습니다. 그러나 여기의 수표는 유형만으로는 안 될 필요가 없습니다. 다른 용도로 사용할 수 있습니다. 예 : 대리자가 Register..
에 전달하면 참조가 특정 유형인지 확인할 필요가 없습니다. '
* 위와 같이 유형 이름으로 사전을 만드는 것은 좋지 않을 수 있습니다. 이 작업은 사용 된 메커니즘을 설명하기 위해 조금 단순합니다.
감사합니다.이 검사가 실행 시간에 완료 되더라도 이것이 가장 가까운 것이라고 생각합니다. 건배 – vdhant