Sana kadarıyla bazı çalışma zamanı kontrolleri kaydetmek için derleyici ve eşdeğer ilaç kullanımıyla olarak şans bitti eminim. Önceden var olmayan bir şeyi geçersiz kılabilirsiniz ve aynı yöntemlere farklı dönüş türlerine sahip olamazsınız.
Motivasyonunuzu tamamen anladığımı söyleyemem ama teknik değeri var.
İlk denemem, Sanal olmayan bir genel arabirime sahip temel sınıfı kullanıyordu ve daha sonra, zincirdeki herhangi bir şeyin, temel sınıf Oluşturma çağrılmadan önce türü denetlemesi için başka bir korunmuş sanal yönteme sahip CheckCreatedType
kullanıyordu.
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.");
}
}
Aşağıdakiler, temel sınıftaki çalışma zamanı denetiminde yapışır.Çözülemeyen sorun, hala çağrılan temel sınıf yöntemine güvenmeniz gerektiğidir. Hatalı bir alt sınıf, tüm denetimleri base.CheckCreatedType(item)
numaralı telefonu arayarak kesebilir.
Alternatifler, temel sınıftaki (alt) tüm alt sınıflar için tüm denetimleri sabitler veya denetimi başka şekilde dışlar.
Deneme 2: (Alt) Sınıflar ihtiyaç duydukları çekleri kaydederler.
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();
}
}
onay taban sınıfta çağırmak için bir temsilci kaydederek alt sınıf tarafından yapılır, ancak açık tüm kuralları bilerek temel sınıf olmadan edilir. Yine de, temel sınıfın bunları geri göndermeden önce sonuçları kontrol etmesine izin veren sanal olmayan genel arabirim olduğuna dikkat edin.
Yakalamayı denediğiniz geliştirici hatası olduğunu varsayalım. Geçerliyse, sürüm sürümünün System.Diagnostics.Conditional("DEBUG")]
ile yapışmasına izin vererek Sürüm sürümünün çekleri atlamasına izin verebilirsiniz.
Jenerik bilgim mükemmel değil, bu yüzden gereksizdir. Ancak, buradaki kontrollerin tek başına yazılması gerekmemektedir: Bu, başka kullanımlar için uyarlanabilir. Örneğin. Register..
içinden geçen temsilci, yalnızca belirli bir tür referansı kontrol etmek zorunda değildir. '
* Yukarıda yazılan tür adında sözlüğü oluşturmak iyi bir şey değildir; Bu çalışma, kullanılan mekanizmayı göstermek için biraz basittir.
Teşekkürler, bu kontrol çalışma zamanında yapılsa bile, bunun en yakın olacağımı düşünüyorum. Cheers – vdhant