我敢肯定你的運氣了儘可能使用編譯器和泛型爲您節省一些運行時檢查。你不能重寫那些不存在的東西,並且你不能有相同方法的不同返回類型。
我不能說我完全理解你的動機,但它具有技術優勢。
我的第一次嘗試是使用具有非虛擬公共接口的基類,然後使用另一個受保護的虛擬方法CheckCreatedType
,它允許鏈中的任何內容在調用基類Create之前檢查該類型。
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 2008-11-13 03:25:06