2014-01-15 6 views
8

В настоящее время я начинаю с расширения Microsoft Dynamics CRM с помощью плагинов.Инъекция зависимостей в MS Dynamics CRM

Можно ли добавлять инъекции зависимостей к этим плагинам (для тестирования, развязки и т. Д.)? Где я могу зарегистрировать свой контейнер IoC, чтобы он использовался во всех плагинах того же типа?

+0

Вы можете проголосовать за эту функцию на https: //ideas.dynamics.com/ideas/dynamics-crm/814208 –

ответ

5

Мы пытались выполнить модульное тестирование и применить инъекцию зависимостей в нашем приложении Dynamics CRM. К сожалению, по мере подтверждения поддержки и консультантов Microsoft, нет способа поддержать это. Вы можете либо перевести всю свою бизнес-логику плагина в другой бизнес-класс, либо применить инъекцию зависимостей или перестать думать об этом.

Если вы решите сражаться с Dynamics CRM, вам нужно определить статическое поле над суперклассом плагина, который будет вашим контейнером DI. Как следует,

public abstract class SuperPlugin : IPlugin{ 
     public void Execute(IServiceProvider serviceProvider){ 
      // initialize a static container instance if not available 
      var containerWrapper = new ContainerWrapper{ 
       Container = serviceProvider.GetService(typeof(IPluginExecutionContext)), 
       Resolver = //static resolver instance of dependency container 
      }; 
      OnExecution(containerWrapper); 
     } 
     public abstract void OnExecution(IDependencyResolver resolver); 
} 

Я действительно не могу понять, почему Microsoft не просто давайте регистрировать некоторые компоненты для реализации IServiceProvider, что они используют внутри.

Ps.Поскольку ваш класс SuperPlugin является IPlugin, вы можете забыть написать реализацию интерфейса в подклассе. Но мы столкнулись с некоторыми ошибками в инструменте регистрации плагинов, который поставляется с официальным SDK Dynamics CRM. Таким образом, в случае, если вы можете иметь ту же проблему, вы также должны реализовать свои плагины следующим образом,

public class MyPlugin : SuperPlugin, IPlugin{ 
    public abstract void OnExecution(IDependencyResolver resolver){}; 
} 

Edit: См небольшой пример, который объясняет концепцию https://github.com/nakahparis/DIForCRM

+0

Хорошее обходное решение. Как бы вы создавали экземпляр средства определения зависимостей? Использование статического класса или одноэлементной структуры? Меня немного беспокоит использование статического резольвера, так как вам понадобится преобразование зависимостей, которое полностью синхронизировано (к нему могут одновременно обращаться несколько потоков) и в то же время достаточно для выполнения многих параллельных плагинов. Любые мысли по этому поводу? –

+1

Да, вы правы, но поскольку нет другого способа, я предпочитаю использовать Lazy <> :) проверить созданный мной gist, https://gist.github.com/msusur/e34be94cbceac20ea364, но вам также необходимо отделить метод установки и Factory для других классов, чтобы применять единую ответственность. –

+0

Отличное решение! Благодаря! –

5

Плагины в CRM являются Бейн модульного тестирования:

  • Проблемы, связанные с испытанием без плагинов
    • Ни в коем случае, чтобы временно отключить
    • Легко забыть, что работает
  • Проблемы с самими тестируемыми плагинами
    • Невозможно выполнить единичные испытания и прикрепляются к обработке
    • много глумиться из, трубопроводов, Поставщик услуг и т.д.
    • Запускает многопоточный

Это привело меня к следующему решению для тестирования плагинов:

  • Избавьтесь от контекста плагина как можно быстрее, извлекая из него все объекты и требуемые сервисы сразу.
  • Создайте метод ExecutePlugin, чтобы подключить модульные тесты и сразу вызвать этот метод после извлечения объектов из контекста плагина.
  • Нажимайте столько кода, сколько возможно в бизнес-слот.

Это приводит к плагинов, которые выглядят, как это (с интенсивным использованием методов расширения, чтобы сделать это проще):

public void Execute(IServiceProvider provider) 
{ 
    var context = provider.GetContext(); 
    var service = provider.GetService(context); 
    var target = GetTarget<Contact>(context); 
    if (target == null || !target.ContainsAllNonNull(c => new 
     { 
      c.FirstName, 
      c.LastName, 
     })) 
    { 
     // Entity is of the wrong type, or doesn't contain all of the required attributes 
     return; 
    } 

    ExecutePlugin(service, target); 
} 

public void ExecutePlugin(IOrganizationService service, Contact target){ 
    // Logic Goes Here 
} 

После того, как это сделано, единственное, что вам нужно модульного тестирования ExceutePlugin является вашим собственным IOrganizationService, который высмеивает необходимые звонки, и вы проводите тестирование устройства. Я даже не утруждаю себя тестированием метода Execute. Либо это сработает, либо не будет, и вздремнуть при первом использовании из CRM.

+0

Спасибо за это хорошее руководство по тестированию в CRM! Мне все еще интересно, что такое инъекция зависимостей, знаете ли вы что-нибудь об этом? –

+0

@ jrosseel Я предполагаю, что это для модульного тестирования? В каких зависимостях вы надеялись насмехаться/заглушить? – Daryl

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