MEF和ASP.NET MVC [英] MEF and ASP.NET MVC

查看:563
本文介绍了MEF和ASP.NET MVC的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用MEF用asp.net mvc的。
我写以下控制器工厂:

 公共类MefControllerFactory:DefaultControllerFactory
{
    私人CompositionContainer中_container;    公共MefControllerFactory(装配组装)
    {
        _container =新CompositionContainer中(新AssemblyCatalog(组装));
    }    保护覆盖一个IController GetControllerInstance(RequestContext的RequestContext的,类型controllerType)
    {
        如果(controllerType!= NULL)
        {
            VAR控制器= _Container.GetExports<一个IController>();            变种controllerExport = controllers.Where(X => x.Value.GetType()== controllerType).FirstOrDefault();            如果(controllerExport == NULL)
            {
                返回base.GetControllerInstance(RequestContext的,controllerType);
            }            返回controllerExport.Value;
        }
        其他
        {
            抛出新的HttpException((Int32)已的HTTPStatus code.NotFound,
                的String.Format(
                    该控制器路径{0}找不到或没有实现一个IController。
                    requestContext.HttpContext.Request.Path
                )
            );
        }
    }
}

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

 保护无效的Application_Start()
    {
        AreaRegistration.RegisterAllAreas();        的RegisterRoutes(RouteTable.Routes);        ControllerBuilder.Current.SetControllerFactory(新MefControllerFactory.MefControllerFactory(Assembly.GetExecutingAssembly()));
    }

我有一个面积:

  [导出(typeof运算(一个IController))]
[PartCreationPolicy(CreationPolicy.NonShared)
公共类HomeController的:控制器
{
    私人只读IArticleService _articleService;    [ImportingConstructor]
    公众的HomeController(IArticleService articleService)
    {
        _articleService = articleService;
    }    //
    // GET:/文章/首页/    公众的ActionResult指数()
    {
        文章文章= _articleService.GetById(55);        返回查看(条);
    }}

IArticleService 是一个接口。

有是实现类 IArticleService 并出口了。

它的工作原理。

这一切我所需要的与MEF工作?

我怎么能跳过设置 PartCreationPolicy ImportingConstructor 为控制器?

我想用构造函数来设置我的依赖关系。

PartCreationPolicy 丢失,我得到以下异常:


  

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



解决方案

我决定回到统一。

我已经创建自定义属性代替MEF的ExportAttribute

  [AttributeUsage(AttributeTargets.Class,的AllowMultiple = FALSE,继承= FALSE)]
公共类ImplementsAttribute:属性
{
    公共ImplementsAttribute(类型合约类型)
    {
        合约类型=合约类型;
    }    公共型合约类型
    {
        得到;
        私人集;
    }
}

例如:

  [工具(typeof运算(ICustomerEmailService))]
公共类CustomerEmailService:ICustomerEmailService
{...}

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

 公共类MyControllerFactory:DefaultControllerFactory
{
    私人只读IUnityContainer _container;    公共MyControllerFactory()
    {
        _container =新UnityContainer();        FUNC<类型,布尔> isController =
            (类型)=> typeof运算(一个IController).IsAssignableFrom(类型)
                    &功放;&安培; (type.IsAbstract || type.IsInterface
                        || type.GetCustomAttributes(typeof运算(生成codeAttribute),TRUE)。任何())=真!;        的foreach(议会大会BuildManager.GetReferencedAssemblies())
        {
            尝试
            {
                变种类型= assembly.GetTypes();                //注册还有所有控制器
                从类型牛逼VAR controllerTypes =其中isController(T)
                                        选择吨;
                的foreach(在controllerTypes T型)
                {
                    _container.RegisterType(T);
                }
                //注册所有供应商
                VAR提供商=
                    从类型Ť
                    从t.GetCustomAttributes出口(typeof运算(ImplementsAttribute),真).OfType< ImplementsAttribute>()
                    选择新的{export.ContractType,供应商= T};                的foreach(在供应商VAR项)
                {
                    如果(item.ContractType!= NULL)
                    {
                        _container.RegisterType(item.ContractType,item.Provider);
                    }
                    其他
                    {
                        _container.RegisterType(item.Provider);
                    }
                }
            }
            抓住
            {
            }
        }
    }    保护覆盖一个IController GetControllerInstance(RequestContext的RequestContext的,类型controllerType)
    {
        如果(controllerType!= NULL)
        {
            VAR控制器= _container.Resolve(controllerType)作为一个IController;            如果(控制== NULL)
            {
                返回base.GetControllerInstance(RequestContext的,controllerType);
            }            返回控制器;
        }
        抛出新的HttpException((Int32)已的HTTPStatus code.NotFound,
            的String.Format(
                该控制器路径{0}找不到或没有实现一个IController。
                requestContext.HttpContext.Request.Path)
        );
    }
}

这是太困难了,我修为MEF的控制器工厂所有的问题:(

I want to use MEF with asp.net mvc. I wrote following controller factory:

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
                )
            );
        }
    }
}

In Global.asax.cs I'm setting my controller factory:

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

        RegisterRoutes(RouteTable.Routes);

        ControllerBuilder.Current.SetControllerFactory(new MefControllerFactory.MefControllerFactory(Assembly.GetExecutingAssembly()));
    }

I have an area:

[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);
    }

}

IArticleService is an interface.

There is a class which implements IArticleService and Exports it.

It works.

Is this everything what I need for working with MEF?

How can I skip setting PartCreationPolicy and ImportingConstructor for controller?

I want to set my dependencies using constructor.

When PartCreationPolicy is missing, I get following exception:

A single instance of controller 'MvcApplication4.Areas.Articles.Controllers.HomeController' cannot be used to handle multiple requests. If a custom controller factory is in use, make sure that it creates a new instance of the controller for each request.

解决方案

I decided to return to Unity.

I've create a custom attribute instead of MEF's ExportAttribute

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

    public Type ContractType
    {
        get; 
        private set;
    }
}

Example:

[Implements(typeof(ICustomerEmailService))]
public class CustomerEmailService : ICustomerEmailService
{...}

And a custom controller factory:

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)
        );
    }
}

It was too difficult for me to fix all problems for MEF's controller factory :(

这篇关于MEF和ASP.NET MVC的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆