Как обратиться к методу? - PullRequest
       2

Как обратиться к методу?

0 голосов
/ 30 декабря 2010

Я пытаюсь создать маршрутизатор для веб-приложения (да, я знаю, что решения уже существуют).

Пока у меня есть это:

class Route
{
    public static RegexOptions DefaultOptions = RegexOptions.IgnoreCase;

    Regex regex;
    Type controller;
    MethodInfo action;

    public Route(string pattern, Type controller)
    {
        this.regex = new Regex(string.Format("^(?:{0})$", pattern), DefaultOptions);
        this.controller = controller;
    }
}

И это:

    Route[] routes = {
        new Route(@"/user:(?<id>\d+)", typeof(UserController))
    };

Когда URL соответствует этому регулярному выражению, он должен вызвать метод action в классе controller.Я думаю, что typeof() - единственный способ передать класс, но как насчет метода?

Я думаю, MethodInfo - это объект, который я хочу, потому что с этим я должен иметь возможность вызыватьэто, но с точки зрения API, каким должен быть 3-й аргумент конструктора Route, и как мы должны его называть?

Я предпочитаю строго типизированное решение, а не некоторые строковые махинации.

Ответы [ 3 ]

3 голосов
/ 30 декабря 2010

Я не думаю, что есть способ ссылаться на метод экземпляра в диезе без экземпляра. Если вы не хотите, чтобы пользователь API определял объект MethodInfo для передачи, наилучшим способом может быть имя строки.

static class Program
{
    static void Main()
    {
        Route r = new Route("pattern", typeof(UserController), "Action");
    }
}

public class Route
{
    public Route(string pattern, Type type, string methodName)
    {
        object objectToUse = Activator.CreateInstance(type, null);
        MethodInfo method = type.GetMethod(methodName);
        string[] args = new string[1];
        args[0] = "hello world";
        method.Invoke(objectToUse, args);
    }
}

public class UserController
{
    public void Action(string message)
    {
        MessageBox.Show(message);
    }
}
1 голос
/ 30 декабря 2010

Вы можете создать что-то вроде этого:

MethodInfo GetMethodInfo(LambdaExpression expression)
{
    var call = expression.Body as MethodCallExpression;
    if(call == null) throw new ArgumentException("Must be a method call","expression");
    return call.Method;
}

MethodInfo GetMethodInfo<T>(Expression<Action<T>> expression)
{
    return GetMethodInfo(expression);
}

MethodInfo GetMethodInfo<T, TResult>(Expression<Func<T, TResult>> expression)
{
    return GetMethodInfo(expression);
}

И использовать это так:

MethodInfo action = GetMethodInfo((UserController c) => c.ActionMethod());
// or
MethodInfo action = GetMethodInfo((UserController c) =>
                                        c.ActionMethodWithParams(default(int)));

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

1 голос
/ 30 декабря 2010

Вы ищете несуществующий оператор infoof .

К сожалению, его не существует.

Самый простой ответ - взятьstring.
В качестве альтернативы, вы можете взять дерево выражений .
Недостатком использования дерева выражений является то, что вызывающая сторона должна передавать все параметры.
Вы можете использовать это в своей структуре (взяв Expression<Func<parameters, ResultType>>), и, возможно, даже скомпилировать дерево выражений для вызова действий.(что приведет к гораздо более быстрым вызовам, чем к отражению)

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