2010-02-22 159 views
17

我試圖在使用lambda表達式的類型上獲取方法的名稱。我正在使用Windows Identity Foundation,需要使用名稱空間作爲資源和方法名稱作爲操作來定義類型名稱的訪問策略。這是一個例子。獲取使用Lambda表達式的方法名稱

這是我會得到的類型名稱和方法名類型從:

namespace My.OrderEntry { 
    public class Order { 
     public void AddItem(string itemNumber, int quantity) {} 
    } 
} 

這就是我想通過DSL來定義訪問策略:

ForResource<Order>().Performing(o => o.AddItem).AllowUsersHaving(new Claim()); 

從該聲明中,我希望將「My.OrderEntry.Order」作爲資源並將「AddItem」作爲該操作。使用名稱空間獲取類型名稱是沒有問題的,但我不認爲我可以使用lambda作爲我想要做的方法。

public static IPermissionExp Performing<T>(
    this IActionExp<T> exp, 
    Func<T, delegate???> action) {} //this is where I don't know what to define 

這種事情甚至可以做到嗎?有沒有另一種方法來做這種事情,而不使用魔術字符串?

+0

AddItem應該添加什麼? – pdr 2010-02-22 21:36:10

+0

AddItem的作用並不重要,我只需要不使用魔術字符串的方法的名稱。 – awilinsk 2010-02-22 21:38:54

+0

這種事很重要。我認爲你的目標是一個行動但我不認爲這是最好的答案。 – pdr 2010-02-22 21:42:06

回答

7

有兩種方法可以做到這一點:

1:你可以做的是採取各種FuncAction代表重載(如Expression<Func<T, Func<TParam1,TParam2, TReturn>>請注意,您的來電將需要顯式地指定泛型參數,無論是在。方法調用或通過創建委託這將這樣來使用:

ForResource<Order>().Performing(o => new Action<string>(o.AddItem)).AllowUsersHaving(new Claim()); 

2:你可以採取包含一個方法調用的Expression<Action>,並解析出從表達式樹調用。這將這樣來使用:

ForResource<Order>().Performing(o => { o.AddItem(null); }).AllowUsersHaving(new Claim()); 
+0

1)我可以使用「對象」而不是「TParam1」嗎? 2)任何方式做到這一點,而不指定空參數? – awilinsk 2010-02-22 21:45:33

+0

+1。我無法提出比第二個例子更通用的版本。 – Skurmedel 2010-02-22 22:26:54

+0

@Wili:1)否 - 代表不是協變的。 2)第 – SLaks 2010-02-22 23:33:30

0

您可以將它作爲Action傳遞,而不強制任何返回類型。但它仍然有點混亂,因爲你必須傳遞一些參數給該方法才能編譯。

+1

行動會奏效,但我真的不關心這些爭論。我可以做類似於:Func ,Func >,Func > – awilinsk 2010-02-22 21:40:59

1

我最近做了一件事情,在那裏你定義了一個使用lambda的方法,然後內部對象取了名字。你也可以使用字符串,或者傳入一個MethodInfo,但是第一個字符不是安全的(而且拼寫錯誤是一個很大的風險),而後者不是很優雅。

基本上,我有過這樣的方法(這是不準確的方法,它是一個比較高級):

public void SetRequest(Request req, Expression<Func<Service, Func<long, IEnumerable<Stuff>>> methodSelector); 

這裏的關鍵是「表達」的東西,這可以讓你「中選擇」一個像這樣的方法:

SetRequest(req, service => service.SomeMethodTakingLongReturningStuffs); 

方法選擇器被製成一個表達式樹,然後您可以從中獲取不同的數據位。我不記得究竟結果樹是什麼樣子,它也取決於你的lambda表達式。

+0

我必須知道該方法簽名。如果我有不同簽名的方法,那麼對於我遇到的每個簽名都必須使用不同的表達式。 – awilinsk 2010-02-22 21:43:20

+0

是的,您可以使用表達式或Expression。 – Skurmedel 2010-02-22 21:48:09

+0

我已經完成(這個IActionExp exp,Func >動作)。這不會編譯。 – awilinsk 2010-02-22 21:52:50

3

它看起來這是你在找什麼,如果你想在給執行函數傳遞動作委託方法的名稱。

public static IPermissionExp Performing<T>( 
    this IActionExp<T> exp, 
    Expression<Action<T, string, int>> action) 
{ 
    var expression = action.Body as MethodCallExpression; 
    string actionMethodName = string.Empty; 
    if (expression != null) 
    { 
     actionMethodName = expression.Method.Name; 
    } 
    // use actionMethodName ("AddItem" in the case below) here 
} 

這將允許您調用像這樣的方法...

ForResource<Order>().Performing((o, a, b) => o.AddItem(a, b)).AllowUsersHaving(new Claim()); 
+1

當然,這需要調用者知道和陳述的論據。顯然,不是你的第一選擇給你評論其他答案:-( – 2010-02-23 00:46:53