2013-09-03 1 views
1

Я создаю приложение Microsft MVC4 с интеграцией MEF и Unity для обработки архитектуры плагина (другие проекты MVC4) и их зависимостей. Однако я получаю сообщение об ошибке при выборе импортированного контроллера MEF, который содержит зависимость Unity. Вот ошибка:Ошибка интеграции MEF + Unity в приложении MVC4

1) Невозможно создать экземпляр типа «X», потому что конструктор не может быть выбран для построения. Убедитесь, что тип имеет конструктор по умолчанию или один конструктор, отмеченный «System.ComponentModel.Composition.ImportingConstructorAttribute».

Основной MVC4 приложение MEF + интеграция Unity код:

// Create MEF catalog from plugin directory. 
var aggregateCatalog = new AggregateCatalog(new DirectoryCatalog(HostingEnvironment.MapPath("~/bin"), "*.dll")); 

// Setup Unity container based on catalog. 
var unityContainer = new UnityContainer(); 
unityContainer.RegisterCatalog(aggregateCatalog); 

// Register dependancy. 
unityContainer.RegisterType<ISystemService, SystemService>(); 

// Compose the MEF container. 
CompositionContainer container = new CompositionContainer(aggregateCatalog, true); 
container.ComposeParts(aggregateCatalog.Catalogs); 

// Register the controller factory that will handle requests. 
ControllerBuilder.Current.SetControllerFactory(new MefControllerFactory(container)); 
var dependencyResolver = System.Web.Http.GlobalConfiguration.Configuration.DependencyResolver; 
System.Web.Http.GlobalConfiguration.Configuration.DependencyResolver = new MefDependencyResolver(container); 

Метод CreateController для выбора правильного контроллера от MEF

// Get all the exported controllers. 
var exports = _container.GetExports<IController, INameMetadata>(); 

// Select controller based off meta data. 
var controller = exports.Where(e => e.Metadata.Name.ToLower().Equals(controllerName.ToLower()) 
      && e.Metadata.Module.ToLower().Equals(module.ToLower())) 
    .Select(e => e.Value).FirstOrDefault();    

Комплекса из контроллера я пытаюсь импортировать. Это подкласс абстрактного базового класса.

Базовый класс.

public abstract class WidgetController : Controller 
{ 

    [Dependency] 
    public ISystemService _systemService { get; set; } 

    [ImportingConstructor] 
    public WidgetController(ISystemService systemService) 
    { 
     _systemService = systemService; 
    } 
} 

Детский класс.

[InheritedExport(typeof(IController))] 
[ExportMetadata("Module", "TheComponent")] 
[ExportMetadata("Name", "TheName")] 
[PartCreationPolicy(CreationPolicy.NonShared)] 
public class WidgetXController : WidgetController 
{  
    public WidgetXController (ISystemService systemService) 
     : base(systemService) 
    {  
    } 
} 

С этой структурой WidgetXController доступен как экспорт в методе CreateController. Однако при попытке выбрать его в запросе LINQ я получаю вышеуказанное сообщение об ошибке. Я попытался добавить атрибут [ImportingConstructor] к дочернему классу, но это приводит к тому, что контроллер попадает в список экспорта. Я думаю, что что-то не совсем правильно настроено в интеграции MEF + Unity ...

Есть ли у кого-нибудь представление о том, как функции интеграции MEF + Unity могут помочь в устранении ошибки, которую я вижу?

ответ

1

Я нашел решение. Вместо создания нового контейнера для композиции мне нужно было получить его от Unity.

Так оригинал код:

// Compose the MEF container. 
CompositionContainer container = new CompositionContainer(aggregateCatalog, true); 
container.ComposeParts(aggregateCatalog.Catalogs); 

// Register the controller factory that will handle requests. 
ControllerBuilder.Current.SetControllerFactory(new MefControllerFactory(container)); 
var dependencyResolver = System.Web.Http.GlobalConfiguration.Configuration.DependencyResolver; 
System.Web.Http.GlobalConfiguration.Configuration.DependencyResolver = new MefDependencyResolver(container); 

становится:

// Obtain the MEF container from Unity 
var mefContainer = unityContainer.Resolve<CompositionContainer>(); 
mefContainer.ComposeParts(this); 

// Register the controller factory that will handle requests. 
ControllerBuilder.Current.SetControllerFactory(new MefControllerFactory(mefContainer)); 
var dependencyResolver = System.Web.Http.GlobalConfiguration.Configuration.DependencyResolver; 
System.Web.Http.GlobalConfiguration.Configuration.DependencyResolver = new MefDependencyResolver(mefContainer);