MEF和ASP.NET MVC [英] MEF and 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
andImportingConstructor
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屋!