2013-04-04 2 views
-1

У меня есть простой класс:Как создать делегат для общего метода?

class Test 
{ 
    public static int Test<T>(T arg) 
    { 
     return 1; 
    } 
} 

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

+1

Что вы пытаетесь достичь? Как бы вы использовали такой делегат? –

+0

@ DanielHilgarth, я собираюсь проверить его с помощью Reflection и испустить код, который его вызывает. – Impworks

+1

Почему делегат тогда в первую очередь? Почему бы не проверить метод напрямую? –

ответ

2

Вы не хотите использовать делегата здесь. Вы хотите MethodInfo экземпляр:

void ImportMethod(string name, MethodInfo method) 

Вы назвали бы это так:

void ImportMethod("Test", typeof(Test).GetMethod("Test", ...Static)); 
+0

Итак, пользователь должен будет использовать Reflection для получения 'MethodInfo' для метода? – Impworks

+0

@Impworks: Да. Возможно, вы сможете немного упростить это, предоставив вспомогательные методы. –

0

Кажется, что Func и Action - это то, что вы ищете.

Вы можете использовать следующее, чтобы получить "делегат объект"

Func<int> func =() => Test<Foo>(bar); 

Вы можете использовать

void ImportMethod(string name, Action action) 

или

void ImportMethod(string name, Func<int> func) 

в зависимости от того, требуется ли возвращаемое значение и зарегистрируйтесь как это

ImportMethod("Name",() => Test<Foo>(bar)) 
+0

Таким образом, я теряю универсальность метода. – Impworks

+0

@Impworks Я не понимаю, что вы имеете в виду. У вас все еще есть генерики, когда вы его регистрируете, но в методе, который вызывает делегата, он заботится только о том, чтобы он возвращал int. Или, возможно, вы, вероятно, очень много разбираетесь в этом методе. Как вы узнаете, что передать каждому методу? как их назвать? –

0
public delegate int Del<T>(T item); 
+0

Это создает тип делегата, в то время как я хочу _объект_ типа 'System.Delegate'. – Impworks

1

Если вы пишете метод с использованием дженериков, чтобы сохранить безопасность типов, вам нужно будет написать два метода для каждого метода, имеющий другое количество входных параметров, одно для метода void (Action) и одно для метода, возвращающего значение (Func). Я выбрал вспомогательный класс, потому что он сокращает количество общих параметров, которые вы должны передать для каждого импорта метода. Это также помогает с intellisense при вызове метода.

public class Foo 
    { 
     public void Bar() 
     { 
     } 

     public void Bar(string input) 
     { 
     } 

     public bool BarReturn() 
     { 
      return false; 
     } 
    } 

    public class ImportHelper<TClass> 
    { 
     public void Import(string name, Expression<Action<TClass>> methodExpression) 
     { 
      ImportMethod(name, methodExpression); 
     } 

     public void ImportMethodWithParam<TParam>(string name, Expression<Action<TClass, TParam>> methodExpression) 
     { 
      ImportMethod<TClass, TParam>(name, methodExpression); 
     } 

     public void ImportMethodWithResult<TResult>(string name, Expression<Func<TClass, TResult>> methodExpression) 
     { 
      ImportMethod<TClass, TResult>(name, methodExpression); 
     } 
    } 

    private static void TestImport() 
    { 
     ImportMethod<Foo>("MyMethod", f => f.Bar()); 
     ImportMethod<Foo, string>("MyMethod1", (f, p) => f.Bar(p)); 
     ImportMethod<Foo, bool>("MyMethod2", f => f.BarReturn()); 

     var helper = new ImportHelper<Foo>(); 
     helper.Import("MyMethod", f => f.Bar()); 
     helper.ImportMethodWithParam<string>("MyMethod1", (f, p) => f.Bar(p)); 
     helper.ImportMethodWithResult("MyMethod2", f => f.BarReturn()); 
    } 

    public static void ImportMethod<TClass>(string name, Expression<Action<TClass>> methodExpression) 
    { 
     var method = GetMethodInfo(methodExpression.Body as MethodCallExpression); 
     //Do what you want with the method. 
    } 

    public static void ImportMethod<TClass, TParam>(string name, Expression<Action<TClass, TParam>> methodExpression) 
    { 
     var method = GetMethodInfo(methodExpression.Body as MethodCallExpression); 
     //Do what you want with the method. 
    } 

    public static void ImportMethod<TClass, TResult>(string name, Expression<Func<TClass, TResult>> methodExpression) 
    { 
     var method = GetMethodInfo(methodExpression.Body as MethodCallExpression); 
     //Do what you want with the method. 
    } 

    private static MethodInfo GetMethodInfo(MethodCallExpression methodCallExpression) 
    { 
     if (methodCallExpression == null) 
      return null; 

     return methodCallExpression.Method; 
    }