Сгенерированные асинхронные вызовы методов в С# - АОП?

Я работаю над приложением WPF, которое использует уровень BusinessLogic (в настоящее время это одна dll), в котором я создал свои методы BL, которые будут вызываться непосредственно из пользовательского интерфейса. Каждый менеджер BL разрешается с помощью Unity (хотя подумываю о переходе на MEF...). Классы BL реализуют определенный интерфейс, который, конечно же, имеет соответствующие методы.

Теперь я хочу создать (или, скорее, СОЗДАТЬ) новую сборку, подобную асинхронному аспекту (или больше...), которая должна иметь аналогичные методы/операции, определенные как в моей исходной сборке (те же параметры...) а также делегат обратного вызова в качестве параметра. Итак, в основном я хочу, чтобы асинхронные методы генерировались с какой-то структурой...

Помимо обычного вызова: User userBO = Resolve().Login("name", "pass"); Я хотел бы использовать что-то подобное с: Resolve().Login("name", "pass", delegate(object, SomeArgs e) { User userBO = e.Args....};

Теперь я хочу, чтобы эта сборка создавалась вместо написания новых аргументов событий и делегатов для каждого метода. Я знаю, что PostSharp может помочь в задаче АОП, но я не смог найти ничего об этом механизме генерации кода в новой dll для асинхронных методов.

Есть ли способ добиться этого с помощью стороннего инструмента или мне нужно переписать всю асинхронную вещь вручную?

Любые идеи приветствуются. Спасибо.


person Stefan Szasz    schedule 26.07.2010    source источник
comment
Вы всегда можете написать свой собственный инструмент для создания пар методов BeginXXX EndXXX и поместить их в разделяемый класс — аналогично тому, как работает генерация кода веб-сервиса. Устройство кода в основном такое же, поэтому это идеальный кандидат для автоматизации. Я не знаю стороннего инструмента для этой цели.   -  person Adam Houldsworth    schedule 26.07.2010


Ответы (1)


Я не знаю инструмента, который сделает это за вас, но есть простой способ обернуть их в Task объекты. По крайней мере, это проще, чем вручную определять Async методов и event обратных вызовов.

Общая концепция состоит в том, чтобы запустить метод как Task, а затем запланировать продолжение задачи в поток пользовательского интерфейса.

Во-первых, определите планировщик (вам не нужно делать это каждый раз, это может быть глобальная переменная или переменная уровня окна):

TaskScheduler ui = TaskScheduler.FromCurrentSynchronizationContext();

затем, когда вы хотите вызвать метод и обработать его возвращаемое значение:

var bll = Resolve();
Task.Factory.StartNew(_ => bll.Login("name", "pass"))
  .ContinueWith(task =>
  {
    // Note: accessing Result will raise any exceptions thrown by Login
    User userBO = task.Result;
    ...
  }, ui);

Это не так красиво, как предложенный вами синтаксис, но его можно использовать. Продолжение задачи, переданное ContinueWith, будет выполняться в потоке пользовательского интерфейса, поэтому безопасно обновлять пользовательский интерфейс или любые объекты с привязкой к данным.

Task объекты также полностью поддерживают другие распространенные асинхронные сценарии, в частности отчеты об отмене и ходе выполнения.

Поскольку этот подход фактически не добавляет события в класс, должна быть возможность написать шаблон T4 для создания методов расширения (например, LoginTask(string username, string password, Action<Task<User>> continuation)).

person Stephen Cleary    schedule 26.07.2010
comment
Выглядит интересно - как это ведет себя при блокировке задачи? Пользовательский интерфейс блокирует? - person Adam Houldsworth; 26.07.2010
comment
Спасибо, ребята, за информацию, мне нужно покопаться в шаблонах T4. Пока я использовал их только в EF. Я думал об асинхронных интерфейсах из-за синтаксического сахара, который он предоставляет: IUser blUser = Resolve().Login(...) и затем IUserAsynchronous = Resolve().LoginAsync(...., callback)... - person Stefan Szasz; 26.07.2010
comment
Я думаю, что собираюсь написать этот инструмент сам. Было бы неплохо, если бы этот инструмент создавал асинхронные методы всякий раз, когда я, например, создаю новый метод BL и создаю проект. просто мысли... Чтобы выходная асинхронная dll также содержала соответствующий асинхронный метод.... - person Stefan Szasz; 26.07.2010
comment
Лично я предпочитаю продолжения задач. Но если вам нравится стиль IAsyncInvoke, обратите внимание, что класс Task на самом деле реализует IAsyncInvoke. Таким образом, вы можете вернуть его из своего метода BeginLogin и получить результат в своем методе EndLogin. - person Stephen Cleary; 26.07.2010