2016-09-07 9 views
2

Возможно ли в C# получить ссылку на функцию-член без указания объекта, так что он можно использовать как статический метод расширения, взяв объект как первый параметр?Метод элемента C# как статический метод («метод обратного расширения»)

class Handler 
{ 
    public void Add(int value) { ... } 
} 

static class HandlerExtensions 
{ 
    public static void AddEx(this Handler instance, int value) { ... } 
} 


var x = new Handler(); 

// possible: 
Action<int> func1 = x.Add; 
Action<Handler, int> func2 = HandlerExtensions.AddEx; 

// not possible? 
Action<Handler, int> func3 = Handler::Add; 

Зачем мне это нужно? Чтобы указать методы для вызова в классе до того фактического объекта для работы с:

// current solution: 
void RegisterDto<DataType>(Func<Handler, Action<DataType>> handler) { ... } 
RegisterDto<int>(x => x.Add); 

// desired solution: 
void RegisterDto<DataType>(Action<Handler, DataType> handler) { ... } 
RegisterDto<int>(Handler::Add); // <--- does syntax for this exist? 
+0

Моя первая путаница в том, что где вы положили «// невозможно?» у вас нет метода '' '' ', который соответствует этой сигнатуре' Action '. Моя вторая - это то, что «X» - ваш класс называется «Handler» - не должен ли он быть «var x = new Handler()»? – Jamiec

+0

@Jamiec Извините, X является обработчиком – AyCe

+0

так и думал - но мой первый вопрос ....? – Jamiec

ответ

7

Если вы имеете в виду «вы можете создать делегат как это», то ответ «да, но это немного некрасиво». Я не думаю вы можете использовать преобразование группы методов, но вы можете использовать отражение и Delegate.CreateDelegate, например.

MethodInfo method = typeof(Handler).GetMethod("Add"); 
var action = (Action<Handler, int>) 
    Delegate.CreateDelegate(typeof(Action<Handler, int>), method); 

Было бы неплохо, если бы здесь было преобразование группы методов, я согласен.

+0

Спасибо. Это уродливо, но близко к тому, что я искал. – AyCe

2

Это не может работать для вас вариант использования, но вы можете создать делегат с

Action<Handler, int> f = (h, v) => h.Add(v); 

И использовать его

var handler = new Handler(); 
f(handler, 100); 
+0

Спасибо за ответ, я знаю, что вы можете это сделать. Я уже создаю делегат для «выбора» метода corrent для обработки заданного типа DataType, но он оценивается каждый раз при вызове обработчика. Я думал о прямом указании метода в классе и использовать конкретный Handler-объект (созданный в будущем), чтобы вызвать его с помощью одного вызова. – AyCe

1

Если вы не хотите, чтобы оценить его каждый раз, , возможно, вы могли бы это сделать Lazy

 Func<Lazy<Handler>, Action<int>> addMethod = target => target.Value.Add; 
     // example of usage 
     var lazyHandler = new Lazy<Handler>(); 
     Test(addMethod(lazyHandler), 1); 

 Смежные вопросы

  • Нет связанных вопросов^_^