Asp.net mvc mvc 4 mef导入/导出混淆
我很难理解Mef和进出口是如何运作的。我的项目结构如下Asp.net mvc mvc 4 mef导入/导出混淆,asp.net-mvc,asp.net-mvc-4,mef,Asp.net Mvc,Asp.net Mvc 4,Mef,我很难理解Mef和进出口是如何运作的。我的项目结构如下 Projects: MefMVPApp (Main MVC 4 app) MefMVCFramework.Common(Interfaces shared between the projects) MefMVCDemo.Plugins.OrderStatus (pluggable area.) MefMVCDemo.Plugins.Data (Repository for OrderStatus) OrderStatus.Models(d
Projects:
MefMVPApp (Main MVC 4 app)
MefMVCFramework.Common(Interfaces shared between the projects)
MefMVCDemo.Plugins.OrderStatus (pluggable area.)
MefMVCDemo.Plugins.Data (Repository for OrderStatus)
OrderStatus.Models(domain models shared between the projects)
主Mvc应用程序的目标是通过mef托管可插入区域
OrderStatus区域有一个名为OrderStatusController的控制器,并用Export属性和ImportingConstructor修饰
[Export(typeof(IController))]
[ExportMetadata("controllerName", "OrderStatus")]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class OrderStatusController : Controller
{
private readonly IRepository<OrderStatusApp.OrderStatusResponse>_repository ;
[ImportingConstructor]
public OrderStatusController(IRepository<OrderStatusApp.OrderStatusResponse> oRepository)
{
_repository = oRepository;
}
public ActionResult Index()
{
var model = _repository.GetAll();
return View();
}
}
我可以看到我的进口
mefx /dir:C:\
Source.PreBranch.Keep\Prototypes\Projects\MefDemoApp\mefMVC4App\bin /imports
MefMVCFramework.Common.IRepository(OrderStatus.Models.OrderStatusApp+OrderStatus
Response)
MefMVCFramework.Common.IRepository(OrderStatus.Models.OrderStatusApp+OrderStatus
Response)
现在,当使用/orderstatus uri浏览我的主mvc站点时,我发现以下错误:
没有为此对象定义无参数构造函数
向OrderStatusController添加不接受重载的默认构造函数似乎不起作用
我想问题是我做错了什么?为什么我在构造函数中的接口最终都是空的,为什么“没有为这个对象定义无参数构造函数”会出现mvc错误 MVC中的默认控制器工厂尝试使用无参数构造函数创建控制器。如果要更改此行为,则需要创建自己的自定义控制器工厂 在控制器上使用导入/导出的ControllerFactory的 我使用MEF将一些部件导入我的应用程序,但我的控制器没有导入/导出,因此我创建了以下控制器工厂
public class ControllerFactory : IControllerFactory
{
private readonly CompositionContainer _container;
private IControllerFactory _innerFactory;
/// <summary>
/// Constructor used to create the factory
/// </summary>
/// <param name="container">MEF Container that will be used for importing</param>
public ControllerFactory(CompositionContainer container)
{
_container = container;
_innerFactory = new DefaultControllerFactory();
}
/// <summary>
/// Method used for create the controller based on the provided name. It calls the
/// constructor of the controller passing the MEF container
/// </summary>
/// <param name="requestContext">Context of the request</param>
/// <param name="controllerName">Name of the controller provided in the route</param>
/// <returns>The controller instance</returns>
public IController CreateController(System.Web.Routing.RequestContext requestContext, string controllerName)
{
Type controllerType = FindControllerByName(controllerName);
var args = new object[] { this._container };
var controller = (IController)Activator.CreateInstance(controllerType, args);
return controller;
}
/// <summary>
/// This methods looks into the current Assembly for the Controller type
/// </summary>
/// <param name="name">The controller name provided in the route</param>
/// <returns>The controller type</returns>
private static Type FindControllerByName(string name){
var a = Assembly.GetAssembly(typeof(ControllerFactory));
var types = a.GetTypes();
Type type = types.Where(t => t.Name == String.Format("{0}Controller", name)).FirstOrDefault();
return type;
}
public System.Web.SessionState.SessionStateBehavior GetControllerSessionBehavior(System.Web.Routing.RequestContext requestContext, string controllerName)
{
return System.Web.SessionState.SessionStateBehavior.Default;
}
public void ReleaseController(IController controller)
{
var disposableController = controller as IDisposable;
if (disposableController != null)
{
disposableController.Dispose();
}
}
公共类控制器工厂:IControllerFactory
{
私有只读合成容器_容器;
私人IControllerFactory\u内部工厂;
///
///用于创建工厂的构造函数
///
///将用于导入的MEF容器
公共控制器工厂(合成容器)
{
_容器=容器;
_innerFactory=新的DefaultControllerFactory();
}
///
///方法用于根据提供的名称创建控制器。它调用
///传递MEF容器的控制器的构造函数
///
///请求的上下文
///路由中提供的控制器的名称
///控制器实例
公共IController CreateController(System.Web.Routing.RequestContext RequestContext,string controllerName)
{
类型controllerType=FindControllerByName(controllerName);
var args=新对象[]{this.\u container};
var controller=(IController)Activator.CreateInstance(controllerType,args);
返回控制器;
}
///
///此方法查找控制器类型的当前程序集
///
///路由中提供的控制器名称
///控制器类型
私有静态类型FindControllerByName(字符串名称){
var a=Assembly.GetAssembly(typeof(ControllerFactory));
var types=a.GetTypes();
Type Type=types.Where(t=>t.Name==String.Format(“{0}控制器”,Name)).FirstOrDefault();
返回类型;
}
public System.Web.SessionState.SessionStateBehavior GetControllerSessionBehavior(System.Web.Routing.RequestContext RequestContext,string controllerName)
{
返回System.Web.SessionState.SessionStateBehavior.Default;
}
公共无效释放控制器(IController控制器)
{
var disposableController=控制器为IDisposable;
if(disposableController!=null)
{
disposableController.Dispose();
}
}
}谢谢波里洛塔为我指明了正确的方向 我必须改变一些东西才能让它发挥作用 1.)我在我的MefMVCFramework.Common项目中添加了一个名为INameMetadata的接口
public interface INameMetadata
{
string Name { get; }
}
2.)将控制器导出上的ExportMetadata标记修改为Name、OrderStatus
[Export(typeof(IController))]
[ExportMetadata("Name", "OrderStatus")]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class OrderStatusController : Controller
{
private IRepository<OrderStatusApp.OrderStatusResponse> _repository;
[ImportingConstructor]
public OrderStatusController(IRepository<OrderStatusApp.OrderStatusResponse> oRepository)
{
_repository = oRepository;
}
public ActionResult Index()
{
var model = _repository.GetById(47985);
return View(model);
}
}
谢谢你的回复。我使用上面的代码创建了控制器工厂(我称之为MefControllerFactory),在global.asax文件中添加了以下行。ControllerBuilder.Current.SetControllerFactory(typeof(MefControllerFactory));加载站点时会引发此错误:尝试创建IControllerFactory“MefMVCApp.MefControllerFactory”时出错。确保控制器工厂有公共无参数构造函数。]它有公共无参数构造函数吗?谢谢帮助。控制器工厂就是我丢失的那块。我修改了你给我的代码,现在可以正常工作了。
public class ControllerFactory : IControllerFactory
{
private readonly CompositionContainer _container;
private IControllerFactory _innerFactory;
/// <summary>
/// Constructor used to create the factory
/// </summary>
/// <param name="container">MEF Container that will be used for importing</param>
public ControllerFactory(CompositionContainer container)
{
_container = container;
_innerFactory = new DefaultControllerFactory();
}
/// <summary>
/// Method used for create the controller based on the provided name. It calls the
/// constructor of the controller passing the MEF container
/// </summary>
/// <param name="requestContext">Context of the request</param>
/// <param name="controllerName">Name of the controller provided in the route</param>
/// <returns>The controller instance</returns>
public IController CreateController(System.Web.Routing.RequestContext requestContext, string controllerName)
{
Type controllerType = FindControllerByName(controllerName);
var args = new object[] { this._container };
var controller = (IController)Activator.CreateInstance(controllerType, args);
return controller;
}
/// <summary>
/// This methods looks into the current Assembly for the Controller type
/// </summary>
/// <param name="name">The controller name provided in the route</param>
/// <returns>The controller type</returns>
private static Type FindControllerByName(string name){
var a = Assembly.GetAssembly(typeof(ControllerFactory));
var types = a.GetTypes();
Type type = types.Where(t => t.Name == String.Format("{0}Controller", name)).FirstOrDefault();
return type;
}
public System.Web.SessionState.SessionStateBehavior GetControllerSessionBehavior(System.Web.Routing.RequestContext requestContext, string controllerName)
{
return System.Web.SessionState.SessionStateBehavior.Default;
}
public void ReleaseController(IController controller)
{
var disposableController = controller as IDisposable;
if (disposableController != null)
{
disposableController.Dispose();
}
}
public interface INameMetadata
{
string Name { get; }
}
[Export(typeof(IController))]
[ExportMetadata("Name", "OrderStatus")]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class OrderStatusController : Controller
{
private IRepository<OrderStatusApp.OrderStatusResponse> _repository;
[ImportingConstructor]
public OrderStatusController(IRepository<OrderStatusApp.OrderStatusResponse> oRepository)
{
_repository = oRepository;
}
public ActionResult Index()
{
var model = _repository.GetById(47985);
return View(model);
}
}
public class MefControllerFactory : IControllerFactory
{
private string _pluginPath;
private readonly DirectoryCatalog _catalog;
private readonly CompositionContainer _container;
private DefaultControllerFactory _defaultControllerFactory;
public MefControllerFactory(string pluginPath)
{
_pluginPath = pluginPath;
_catalog = new DirectoryCatalog(pluginPath);
_container = new CompositionContainer(_catalog);
_defaultControllerFactory = new DefaultControllerFactory();
}
public MefControllerFactory(CompositionContainer compositionContainer)
{
_container = compositionContainer;
_defaultControllerFactory = new DefaultControllerFactory();
}
#region IControllerFactory Members
public IController CreateController(System.Web.Routing.RequestContext requestContext, string controllerName)
{
//IController controller = null;
var controller = _container.GetExports<IController,INameMetadata>()
.Where(e=>e.Metadata.Name.Equals(controllerName))
.Select(e=>e.Value).FirstOrDefault();
if (controller == null)
{
throw new HttpException(404, "Not found");
}
return controller;
}
public void ReleaseController(IController controller)
{
var disposable = controller as IDisposable;
if (disposable != null)
{
disposable.Dispose();
}
}
#endregion
public SessionStateBehavior GetControllerSessionBehavior(System.Web.Routing.RequestContext requestContext, string controllerName)
{
return SessionStateBehavior.Default;
}
}
public static class MefConfig
{
public static void RegisterMef()
{
//var builder = new RegistrationBuilder();
//builder.ForTypesDerivedFrom<IRepository<OrderStatusApp.OrderStatusResponse>>().Export<IRepository<IRepository<OrderStatusApp.OrderStatusResponse>>>();
var directoryCatalog = new DirectoryCatalog(HostingEnvironment.MapPath("~/bin"), "*.dll");
var container = new CompositionContainer(directoryCatalog, true);
ControllerBuilder.Current.SetControllerFactory(new MefControllerFactory(container));
//Working
//ControllerBuilder.Current.SetControllerFactory(new MefControllerFactory(HostingEnvironment.MapPath("~/bin")));
// Install MEF dependency resolver for MVC
var resolver = new MefDependencyResolver(container);
DependencyResolver.SetResolver(resolver);
// Install MEF dependency resolver for Web API
GlobalConfiguration.Configuration.DependencyResolver = resolver;
var d = container.GetExportedValues<IRepository<OrderStatusApp.OrderStatusResponse>>();
//Mefx.
try
{
//var ci = new CompositionInfo(aggregateCatalog, container);
var ci = new CompositionInfo(directoryCatalog, container);
var partDef = ci.GetPartDefinitionInfo(typeof(IRepository<OrderStatusApp.OrderStatusResponse>));
//var possibleCauses = partDef.FindPossibleRootCauses();
var stringWriter = new StringWriter();
CompositionInfoTextFormatter.Write(ci, stringWriter);
var compStatString = stringWriter.ToString();
}
catch
{
}
MvcApplication.ActionVerbs = container.GetExports<IActionVerb, IActionVerbMetadata>();
}
}
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
//Register Mef
MefConfig.RegisterMef();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
}