Получить имя метода с помощью лямбда-выражения - PullRequest
17 голосов
/ 23 февраля 2010

Я пытаюсь получить имя метода для типа, используя лямбда-выражение. Я использую Windows Identity Foundation и мне нужно определить политики доступа с именем типа с пространством имен в качестве ресурса и именем метода в качестве действия. Вот пример.

Это тип, из которого я получу имя типа и имя метода:

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» в качестве действия. Получение имени типа с пространством имен не проблема, но я не думаю, что могу использовать лямбду для метода, как я пытаюсь сделать.

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

Возможно ли вообще что-либо сделать? Есть ли другой способ сделать это, не используя магические строки?

Ответы [ 4 ]

7 голосов
/ 23 февраля 2010

Есть два способа сделать это:

1: Вы можете создавать перегрузки, которые принимают различные делегаты Func и Action (например, Expression<Func<T, Func<TParam1,TParam2, TReturn>>. Обратите внимание, что ваши вызывающие абоненты должны будут явно указывать общие параметры либо в вызове метода, либо путем создания делегата Это будет использовано так:

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

2: Вы можете взять Expression<Action>, который содержит вызов метода, и проанализировать MethodInfo, вызываемый из дерева выражений. Это будет использовано так:

ForResource<Order>().Performing(o => { o.AddItem(null); }).AllowUsersHaving(new Claim());
3 голосов
/ 23 февраля 2010

Похоже, это то, что вы ищете, если хотите, чтобы имя метода делегата действия было передано в функцию Performing.

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 голос
/ 23 февраля 2010

Недавно я сделал что-то на работе, когда вы определили метод, используя лямбду, которую затем принял внутренний объект. Вы также можете использовать строки или передать MethodInfo, но первая не совсем безопасна для типов (а опечатки представляют большой риск), а последняя не очень элегантна.

В основном у меня был такой метод (это не точный метод, он немного более продвинутый):

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

Ключевым моментом здесь является «выражение», это позволяет вам «выбрать» метод, подобный этому:

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

Селектор метода превращается в дерево выражений, из которого вы можете извлекать различные биты данных. Я не помню точно, как выглядит результирующее дерево, это также зависит от того, как выглядят ваши лямбды.

0 голосов
/ 23 февраля 2010

Вместо этого вы можете передать его как Действие, которое не вызывает тип возврата. Это все еще немного грязно, потому что вы должны передать некоторые аргументы методу для его компиляции.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...