2011-05-10 31 views
8

我有一堆方法,我想檢查一些元數據,他們都有不同的參數,但參數都來自BaseClassFunc <>使用基類作爲參數

public void CheckMethod(Func<BaseClass, Object> func) 
{ 
    // Check method metadata here 
} 

public Object MethodToCheck(DerivedClass foo) 
{ 
    // Whatever... 
} 

public void Test() 
{ 
    CheckMethod(MethodToCheck); 
} 

代碼失敗的CheckMetadata(MethodToCheck),監守MethodToCheck有一個DerivedClass作爲參數,而不是一個BaseClass的。我已經使用泛型嘗試:

public void CheckMethod<T>(Func<T, Object> func) 

... 

CheckMethod<DerivedClass>(MethodToCheck); 

我想調用CheckMethod要儘量少爲可能的類型,寧願只與CheckMethod(MethodToCheck)調用它。這可能嗎?

+1

我很好奇,爲什麼你有使用泛型一個完全可行的解決方案,但你正在尋找的唯一標準是不同的解決方案它應該需要更少的打字。你的目標是什麼?減少編程團隊的RSI? – 2011-05-10 12:19:49

+0

主要原因是我只對實際方法感興趣。但是,參數和返回數據是方法簽名的一部分,所以我想這是不可能的。 – 2011-05-12 06:23:36

+0

這正是我在我的帖子中所說的:)。我認爲這應該被標記爲答案。 – 2011-05-29 10:49:50

回答

2

如何像

public void CheckMethod<T>(Func<T, Object> func) where T : BaseClass 
+0

仍然要求用CheckMethod (MethodToCheck) – 2011-05-10 11:37:26

-2

一種方法是使用dynamic代替BaseClass

public void CheckMethod(Func<dynamic, Object> func) 

然後做一些類型的內CheckMethod檢查,首先檢查參數類型是BaseClass,如果不是,可能會拋出?

+1

調用結果:參數1:無法從'方法組'轉換爲'System.Func ' – 2011-05-10 11:41:12

0

這似乎是C#語言設計者沒有想到的。你(和我)正在尋找的是Funcs/Delegates的編譯時「接口」,所以它們基本上可以用在一個集合中。

問你的問題的另一種方式是我怎麼約束別人傳遞一個這樣的數組:

new[] { 
    new Func<MaxLengthAttribute, string>(a => "maxlength=" + a.Length), 
    new Func<RequiredAttribute, string>(a => "required") 
} 

要只通過格式Func<out Attribute, string>的funcs中?應該是簡單的...不是?

不可以。作爲鏈接的其他答案,out關鍵字不允許輸入參數,如我們在此使用的輸入參數。

如果你必須在你不得不擁有類似Java的醜陋雜技編譯時的約束:

public interface IHasMethod<T> 
    where T : BaseClass 
{ 
    void MethodToCheck<T>(T, object); 
} 

public class Class1 : IHasMethod<DerivedClass> 
{ 
    public object MethodToCheck(DerivedClass d) 
    { 

    } 
} 

這意味着你的測試看起來像:

public void CheckMethod(IHasMethod methodHaver) 
{ 
} 

Eugh。同樣,我的數組示例變爲:new IHasMethod[]

如果您更喜歡在運行時只受保護/檢查的更漂亮,更脆弱的代碼,那麼您的替代方案是Delegate。您的簽名:

public void CheckMethod(Delegate func) 

我的數組例如:

new Delegate[] ... 

但在這兩種情況下,你處於危險之中是因爲這代表的格式是無界的,在編譯時 - 它現在對你做什麼通常成爲編譯器的問題,在繼續之前檢查正確數量的參數及其類型。如果可以的話,嘗試僅在調試代碼中進行醜陋的檢查,並調用解壓縮並暴露給單元測試的方法,以便儘管編譯安全性已經喪失,但應使用自動化測試安全性替換它。像:

#if DEBUG 
     foreach(var attrTempl in attributeTemplates) 
     { 
      var templParams = attrTempl.Method.GetParameters(); 
      if (templParams.Length != 1) 
       throw new Exception("Can't have " + templParams.Length + " params in AttributeTemplate Delegate, must be Func<out Attribute, string>"); 

      var type1 = templParams[0].ParameterType; 
      var type2 = attrTempl.Method.ReturnType; 

      if (!type1.IsSubclassOf(typeof(System.Attribute))) 
       throw new Exception("Input parameter type " + type1.Name + " must inherit from System.Attribute"); 

      if (type2 != typeof(string)) 
       throw new Exception("Output parameter type " + type2.Name + " must be string"); 
     } 
#endif 

對該欄的最後一個幫手:如果你把Delegate方法,你會轉換代碼看起來像這樣:

Func<A, B> fn 

要這樣:

Delegate fn 

您可能在某些時候稱爲Func,如:

var b = fn(a); 

現在會出現編譯錯誤,因爲編譯器準確地聲明它不知道該委託是否接受任何參數。可愛。你可以踢過去它的運行時間:

var b = (B)fn.DynamicInvoke(a); 

Related

相關問題