2013-05-24 5 views
7

Можете ли вы активировать систему модуля Prism из службы WCF? Потому что независимо от того, что я делаю, мои MEF-зависимости не выполняются.Система модуля Prism из службы WCF?

Например:

Это мой WCF сервис реализация

public class MyService : IMyServiceContract{ 
    // This should get filled by MEF after Prism loads the required modules 
    [Import] 
    IDatabase db; 

    public MyService(){ 
     var bootsrapper = new MyServiceBoostrapper(); 
     bootsrapper.Run(); 
    } 
} 

Это мой Prism boostrapper с MEF вкусом:

public class MyServiceBoostrapper : MefBootstrapper 
{ 
    protected override void ConfigureContainer() 
    { 
     base.ConfigureContainer(); 
    } 

    protected override IModuleCatalog CreateModuleCatalog() 
    { 
     return new ConfigurationModuleCatalog(); 
    } 
    protected override void ConfigureAggregateCatalog() 
    { 
     base.ConfigureAggregateCatalog(); 

     // TODO: Add this assembly ... don't know why 
     this.AggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(MyServiceBoostrapper).Assembly)); 
     this.AggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(IDatabase).Assembly)); 
     // This is what provides the service 
     this.AggregateCatalog.Catalogs.Add(new AssemblyCatalog(typeof(DatabaseImpl).Assembly)); 
    } 

    protected override DependencyObject CreateShell() 
    { 
     // we don't need the shell 
     return null; 
    } 

} 

Вот мой модуль что содержит интерфейсов для базы данных службы Prism:

[ModuleExport(typeof(IDatabase))] 
public class ModuleActivator : IModule 
{ 
    public void Initialize() 
    { 
     // Do nothing as this module simply provides the API. 
    } 
} 
public interface IDatabase 
{ 
    // interface methods here ... 
} 

и, наконец, вот службы Prism базы сами:

[ModuleExport(typeof(DatabaseImpl), DependsOnModuleNames = new string[] { "IDatabase" })] 
public class ModuleActivator : IModule 
{ 
    public void Initialize() 
    { 
     // Do nothing as this is a library module. 
    } 
} 

[Export(typeof(IDatabase))] 
public class DatabaseImpl : IDatabase 
{ 
    /// implementation here ... 
} 

Пробовал это в течение последних нескольких часов без успеха. Мой db импорт всегда null и никогда не инициализируется.

Обратите внимание, что все работает, если я делаю все это без призмы, но только с MEF.

+0

А как насчет прогресса в этом вопросе? –

+0

Я думаю, что нашел решение в книге «Инъекция зависимостей в .NET» (часть 3, глава 7.3). Все еще проверяю это. В основном, это просто вопрос подключения к процедуре запуска WCF. – drozzy

+0

Как я уже сказал в своем комментарии. Я действительно думаю, что это проблема настройки вашего контейнера и регистрации типов ... –

ответ

0

Ну, похоже, решение не использовать Prism вообще , поскольку он не добавляет ничего «модульного» с его модулями. Похоже, что модули являются концепциями исключительно для визуальных приложений.

Вместо этого нужно подключиться к процедуре запуска «WCF» WCF и активировать контейнер MEF оттуда. Ответ на то, как это сделать, скорее задействован (хотя и не сложно), так как WCF уже имеет множество точек расширения/крючка.

Ответ, который я использовал, содержится в книге Инъекция зависимостей в .NET Марка Seemann в главе 7.3: «Составление приложений WCF».

Не скопируйте всю главу из этой книги в этот ответ, я боюсь, что это лучшее, что я могу сделать.

1

Я не уверен, что следующие фрагменты помогут вам. У меня есть только опыт работы с PRISM и Unity. Просто попробуйте и скажите мне, что происходит.

protected override void ConfigureContainer() 
    { 
     base.ConfigureContainer(); 

     this.RegisterTypeIfMissing(typeof(IDatabase), typeof(DatabaseImpl), true); 
    } 

Вы также создаете и пустите ModuleCatalog и никогда не настраиваете его.

protected override void ConfigureModuleCatalog() 
     { 

      base.ConfigureModuleCatalog(); 

      var moduleCatalog = (ModuleCatalog)ModuleCatalog; 

      Type Initial = typeof(ModuleActivator); 
      moduleCatalog.AddModule(new ModuleInfo 
      { 
       ModuleName = Initial.Name, 
       ModuleType = Initial.AssemblyQualifiedName 
      }); 
     } 
3

Вы не будет ничего импортировать в ваш db поле, так как объект MyService не создается контейнером - он не может быть создан, потому что контейнер на самом деле создается в загрузчике, который является в конструкторе MyService.

Один простой способ решить этот вопрос - удовлетворить импорт объекта после инициализации контейнера. Для этого, вы можете выставить контейнер в загрузчике так:

public class MyServiceBoostrapper 
{ 
    public CompositionContainer MyServiceContainer 
    { 
     get { return Container; } 
    } 

    // Rest of bootstrapper definitions... 
} 

Затем измените MyService «s конструктор:

public MyService() 
{ 
    var bootsrapper = new MyServiceBoostrapper(); 
    bootsrapper.Run(); 

    // This is an extension method. You'll need to add 
    // System.ComponentModel.Composition to your using statements. 
    bootstrapper.MyServiceContainer.SatisfyImportsOnce(this); 

    // At this stage, "db" should not be null. 
} 
+0

Да, это работает. Благодарю. Конечно, дело в том, что мне даже не нужен Призм. Это просто путало проблему. Кроме того, чтение книги «Dependency Injection in .NET» помогло выяснить, что было сделано где. Особенно их пример того, как загружать WCF. Я слишком устал сегодня, чтобы написать этот ответ здесь, но это будет правильный способ загрузки службы WCF. – drozzy

+0

Да, Prism, вероятно, здесь не обязательно, но я думал, что объяснять, почему все не сработало, поможет вам принять лучшее решение о том, как загружать ваш сервис, а также позволяя вам сохранить текущую реализацию. Во всяком случае, надеюсь, что мой ответ был полезен. –

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