MEF和ASP.NET MVC

den*_*s_n 7 asp.net asp.net-mvc mef

我想在asp.net mvc中使用MEF.我写了以下控制器工厂:

public class MefControllerFactory : DefaultControllerFactory
{
    private CompositionContainer _Container;

    public MefControllerFactory(Assembly assembly)
    {
        _Container = new CompositionContainer(new AssemblyCatalog(assembly));
    }



    protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
    {
        if (controllerType != null)
        {
            var controllers = _Container.GetExports<IController>();

            var controllerExport = controllers.Where(x => x.Value.GetType() == controllerType).FirstOrDefault();

            if (controllerExport == null)
            {
                return base.GetControllerInstance(requestContext, controllerType);
            }

            return controllerExport.Value;
        }
        else
        {
            throw new HttpException((Int32)HttpStatusCode.NotFound,
                String.Format(
                    "The controller for path '{0}' could not be found or it does not implement IController.",
                    requestContext.HttpContext.Request.Path
                )
            );
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

在Global.asax.cs我正在设置我的控制器工厂:

protected void Application_Start()
    {
        AreaRegistration.RegisterAllAreas();

        RegisterRoutes(RouteTable.Routes);

        ControllerBuilder.Current.SetControllerFactory(new MefControllerFactory.MefControllerFactory(Assembly.GetExecutingAssembly()));
    }
Run Code Online (Sandbox Code Playgroud)

我有一个区域:

[Export(typeof(IController))]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class HomeController : Controller
{
    private readonly IArticleService _articleService;

    [ImportingConstructor]
    public HomeController(IArticleService articleService)
    {
        _articleService = articleService;
    }

    //
    // GET: /Articles/Home/

    public ActionResult Index()
    {
        Article article = _articleService.GetById(55);

        return View(article);
    }

}
Run Code Online (Sandbox Code Playgroud)

IArticleService 是一个界面.

有一个实现IArticleService和导出它的类.

有用.

这就是我使用MEF所需要的一切吗?

如何跳过设置PartCreationPolicyImportingConstructor控制器?

我想使用构造函数设置我的依赖项.

什么时候PartCreationPolicy丢失,我得到以下异常:

控制器'MvcApplication4.Areas.Articles.Controllers.HomeController'的单个实例不能用于处理多个请求.如果正在使用自定义控制器工厂,请确保它为每个请求创建控制器的新实例.

den*_*s_n 2

我决定回到Unity。

我创建了一个自定义属性而不是 MEF 的 ExportAttribute

[AttributeUsage(AttributeTargets.Class, AllowMultiple = false, Inherited = false)]
public class ImplementsAttribute : Attribute
{
    public ImplementsAttribute(Type contractType)
    {
        ContractType = contractType;
    }

    public Type ContractType
    {
        get; 
        private set;
    }
}
Run Code Online (Sandbox Code Playgroud)

例子:

[Implements(typeof(ICustomerEmailService))]
public class CustomerEmailService : ICustomerEmailService
{...}
Run Code Online (Sandbox Code Playgroud)

和一个自定义控制器工厂:

public class MyControllerFactory : DefaultControllerFactory
{
    private readonly IUnityContainer _container;

    public MyControllerFactory()
    {
        _container = new UnityContainer();

        Func<Type, bool> isController =
            (type) => typeof(IController).IsAssignableFrom(type)
                    && (type.IsAbstract || type.IsInterface 
                        || type.GetCustomAttributes(typeof(GeneratedCodeAttribute), true).Any()) != true;



        foreach (Assembly assembly in BuildManager.GetReferencedAssemblies())
        {
            try
            {
                var types = assembly.GetTypes();

                // Also register all controllers
                var controllerTypes = from t in types where isController(t) 
                                        select t;


                foreach (Type t in controllerTypes)
                {
                    _container.RegisterType(t);
                }


                // register all providers
                var providers =
                    from t in types
                    from export in t.GetCustomAttributes(typeof(ImplementsAttribute), true).OfType<ImplementsAttribute>()
                    select new { export.ContractType, Provider = t };

                foreach (var item in providers)
                {
                    if (item.ContractType != null)
                    {
                        _container.RegisterType(item.ContractType, item.Provider);
                    }
                    else
                    {
                        _container.RegisterType(item.Provider);
                    }
                }
            }
            catch 
            {
            }
        }
    }



    protected override IController GetControllerInstance(RequestContext requestContext, Type controllerType)
    {
        if (controllerType != null)
        {
            var controller = _container.Resolve(controllerType) as IController;

            if (controller == null)
            {
                return base.GetControllerInstance(requestContext, controllerType);
            }

            return controller;
        }


        throw new HttpException((Int32)HttpStatusCode.NotFound,
            String.Format(
                "The controller for path '{0}' could not be found or it does not implement IController.",
                requestContext.HttpContext.Request.Path)
        );
    }
}
Run Code Online (Sandbox Code Playgroud)

对我来说解决 MEF 控制器工厂的所有问题太困难了:(