首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >mvc 4 mef导入/导出混淆

mvc 4 mef导入/导出混淆
EN

Stack Overflow用户
提问于 2013-04-10 02:31:50
回答 2查看 2.1K关注 0票数 1

我很难理解Mef和进出口的工作原理。我的项目结构如下。

代码语言:javascript
复制
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托管可插拔的区域。

导出区域有一个名为OrderStatusController的控制器,并用OrderStatus属性和一个ImportingConstructor进行装饰。

代码语言:javascript
复制
[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();
            } 
    }

IRepository是MefMVCFramework.Common程序集中的一个类,将用于一般的CRUD操作。

代码语言:javascript
复制
public interface IRepository<T> where T : class
            {
               IEnumerable<T> GetAll();
               T GetById(int id);
               void Add(T entity);
               int SaveOrUpdate(T entity);
                bool Delete(T entity);
                bool Delete(int id); 
            }

导出程序集包含一个名为OrderManagementRepository的类,它继承了通用存储库,并用MefMVCDemo.Plugins.Data属性进行了标记。

代码语言:javascript
复制
[Export(typeof(IRepository<OrderStatusApp.OrderStatusResponse>))]
            [PartCreationPolicy(CreationPolicy.NonShared)] 
                public class OrderManagementRepository  : IRepository<OrderStatusApp.OrderStatusResponse>
                {
                    private readonly JsonServiceClient _client;

                    public OrderManagementRepository()
                    {
                        _client = new JsonServiceClient("http://localhost:52266");
                    }
                    public IEnumerable<OrderStatusApp.OrderStatusResponse> GetAll()
                    {

                        throw new NotImplementedException("Can not get all");
                    }
                    public OrderStatusApp.OrderStatusResponse GetById(int id)
                    {
                        throw new NotImplementedException();
                    }
                    public void Add(OrderStatusApp.OrderStatusResponse entity)
                    {
                        throw new NotImplementedException();
                    }
                    public int SaveOrUpdate(OrderStatusApp.OrderStatusResponse entity)
                    {
                        throw new NotImplementedException();
                    }
                    public bool Delete(OrderStatusApp.OrderStatusResponse entity)
                    {
                        throw new NotImplementedException();
                    }
                    public bool Delete(int id)
                    {
                        throw new NotImplementedException();
                    }
                } 

使用Mefx工具,我能够看到我的零件,没有拒绝。

代码语言:javascript
复制
mefx /dir:C:\
Source.PreBranch.Keep\Prototypes\Projects\MefDemoApp\mefMVC4App\bin /parts
MefMVCDemo.Plugins.Data.OrderManagementRepository
mefMVCDemo.Plugins.OrderStatus.Controllers.OrderStatusController
MefMVCDemo.Plugins.OrderStatus.Verbs.OrderStatusVerb

我可以看到我的导入。

代码语言:javascript
复制
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)

现在,当我使用mvc浏览我的主/orderstatus站点时,我得到了以下错误:没有为这个对象定义无参数的构造函数。

向OrderStatusController添加一个不接受重载的默认构造函数似乎不起作用。

我想问题是我做错了什么?为什么我在构造函数中的接口一直都是空的,为什么有一个关于“没有为这个对象定义无参数构造函数”的mvc错误。

EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2013-04-10 04:57:33

MVC中的默认控制器工厂尝试使用无参数构造函数创建控制器。如果您想要更改此行为,则需要创建自己的自定义控制器工厂。

在控制器上使用导入/导出的ControllerFactory的Here is an example

我正在使用MEF将一些部件导入到我的应用程序中,但是我的控制器没有被导入/导出,所以我创建了以下控制器工厂

代码语言:javascript
复制
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();
    }
}

}

票数 1
EN

Stack Overflow用户

发布于 2013-04-11 02:47:25

感谢pollirrata为我指明了正确的方向。

我必须改变一些东西才能让它正常工作。

1.)我在MefMVCFramework.Common项目中添加了一个名为INameMetadata的接口。

代码语言:javascript
复制
public interface INameMetadata
{
    string Name { get; }
}

2.)将控制器导出上的ExportMetadata标记修改为名称OrderStatus。

代码语言:javascript
复制
 [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);
    } 
}

3.)创建了MefControllerFactory (基于pollirrata发布的内容,但进行了修改以查找元数据)

代码语言:javascript
复制
 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;
    }
}

4.)我在MVC主应用程序中创建了一个名为MefConfig的类,并将其移动到App_Start目录中。

代码语言:javascript
复制
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>();
    }
}

5.)从global.asax加载Mefconfig。

代码语言:javascript
复制
 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);

    }
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/15909795

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档