Устаревший API требует передачи имени обратного вызова в виде строки.Могу ли я улучшить этот API с помощью метода расширения? - PullRequest
2 голосов
/ 17 сентября 2010

Я столкнулся с устаревшим API, который не использует события .NET, а скорее требует от меня сделать это:

// (first arg is System.Object, second arg is string, myFoo is of type Foo)
myFoo.AddCallback(this, "DoSomething(int)");

Этот API требует, чтобы DoSomething был методом экземпляра в this, и чтобы он занимал int.

Есть ли способ, которым я могу использовать этот API для обеспечения безопасности при использовании?

Точнее: Я хочу написать метод расширения для Foo, который позволит мне вызывать AddCallback с делегатом .NET, а не с парой получатель-подпись. Я представляю что-то вроде этого:

// extension method definition
public static void AddCallback(this Foo foo, Action action)
{
    foo.AddCallback(
        FigureOutReceiverOf(action),    // ?
        FigureOutSignatureOf(action));  // ?
}

public static void AddCallback<T>(this Foo foo, Action<T> action)
{ ... } // and so on, for up to, say, 10 type-arguments

// usage:
myFoo.AddCallback(DoSomething)
// or even a lambda:
myFoo.AddCallback((i) => Console.WriteLine(i));

Если это можно сделать с помощью метода взлома расширений, это улучшит мою жизнь. Также мне просто интересно, возможно ли это, учитывая возможности C #.

Кстати, устаревший API называется qt4dotnet.

1 Ответ

3 голосов
/ 17 сентября 2010

Использовать лямбду будет непросто - в конечном итоге это будет метод в другом классе, если он захватывает локальные переменные.Конечно, вы можете обнаружить это, но это не будет безопасным во время компиляции.

Аналогично, часть подписи интересна тем, что если это определенно и Action, то делегатне имеет параметровВы не можете просто сделать параметр Delegate, иначе преобразование группы методов не будет работать ... хотя вы все равно можете вызвать

myFoo.AddCallBack(new Action<int>(MyMethodName));

Альтернативой является создание нескольких перегрузок:

public static void AddCallback(this Foo foo, Action action)

public static void AddCallback<T>(this Foo foo, Action<T> action)

public static void AddCallback<T1, T2>(this Foo foo, Action<T1, T2> action)

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

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

С этими проблемами, разработка сигнатуры составляет относительно просто.Вы используете свойство Delegate.Method, и из него вы можете получить имя и типы параметров.Если для библиотеки требуется "int", а не "System.Int32" и т. Д., Вам понадобится немного поработать над этим, но это не должно быть слишком плохо.(Хотя это звучит как довольно странный API.)

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