1

I am brand new to MEF and am stuck in "No parameterless constructor defined for this object" hell. I've looked at a lot of posts etc. over the last many hours and am totally stuck. What am I doing wrong? I'm using .NET 4.5, so do I still need all these attributes? Am I mixing older style MEF in with newer?

UPDATE:

The solution I'm working on also references Unity 3.3, so I think they may be stepping on each other. Do I need to remove Unity?

    [Export]
    [PartCreationPolicy(CreationPolicy.NonShared)]
    public class HomeController : Controller
    {
        private readonly IHomeService _service;

        [ImportingConstructor]
        public HomeController(IHomeService service)
        {
            _service = service;
        }
    }

    [Export(typeof(IHomeService))]
    [PartCreationPolicy(CreationPolicy.NonShared)]
    public class HomeService : IHomeService
    {
        private readonly IServiceSearch _serviceSearch;

        [ImportingConstructor]
        public HomeService(IServiceSearch serviceSearch)
        {
            _serviceSearch = serviceSearch;
        }
    }

    [InheritedExport]
    public interface IHomeService
    {
       // ...
    }

    [Export(typeof(IServiceSearch))]
    [PartCreationPolicy(CreationPolicy.NonShared)]
    public class ServiceSearch : DataHub.Search, IServiceSearch
    {

        [ImportingConstructor]
        public ServiceSearch(IMapper<xxx, xxxDTO> x)
        {
           // ...
        }

    [InheritedExport]
    public interface IMapper<TDomain,TDto>
    {
        TDomain ToDomain(object o);
        void Initialize();
        TDto DomainToDto(TDomain domain);
    }

 [Export(typeof(IMapper<Account, AccountDTO>))]
    public class AccountMapper : IMapper<Account, AccountDTO>
    {
     //....
    }

    protected void Application_OnStart()
    {            
        var catalog = new AssemblyCatalog(Assembly.GetExecutingAssembly());
        var composition = new CompositionContainer(catalog);
        IControllerFactory mefControllerFactory = new MefControllerFactory(composition); //Get Factory to be used
        ControllerBuilder.Current.SetControllerFactory(mefControllerFactory);
    }

    public class MefControllerFactory : DefaultControllerFactory
    {
        private readonly CompositionContainer _container;
        public MefControllerFactory(CompositionContainer container)
        {
            _container = container;
        }
        protected override IController GetControllerInstance(System.Web.Routing.RequestContext requestContext, Type controllerType)
        {
            Lazy<object, object> export = _container.GetExports(controllerType, null, null).FirstOrDefault();

            return null == export
                                ? base.GetControllerInstance(requestContext, controllerType)
                                : (IController)export.Value;
        }
        public override void ReleaseController(IController controller)
        {
            ((IDisposable)controller).Dispose();
        }
    }
Big Daddy
  • 5,160
  • 5
  • 46
  • 76
  • I've not encountered an error with MEF for `No parameterless constructor defined for this object`; rather, the error will state which object is missing the parameterless .ctor. What is the exact error? Which class is missing the parameterless .ctor? – Metro Smurf Apr 02 '15 at 20:41
  • Looking at the code provided, neither HomeController nor HomeService have parameterless constructors. – Mark Larter Apr 02 '15 at 20:43
  • @MarkLarter...They're not suppose to. If I add one, the dependencies aren't injected – Big Daddy Apr 02 '15 at 20:46
  • @MetroSmurf...It's HomeController, if I add one, then no complaints, but the dependencies aren't injected either – Big Daddy Apr 02 '15 at 20:47
  • You seem to be missing an implementation for `IServiceSearch`... – oɔɯǝɹ Apr 02 '15 at 21:30
  • It looks like a bit of research is needed on how to instruct MEF to use the non-default constructor and supply the dependency you want to inject for this class, assuming MEF supports this sort of thing. You might have a look at this SO question/answer: http://stackoverflow.com/questions/2941158/mef-constructor-parameters-with-multiple-constructors – Mark Larter Apr 03 '15 at 03:02
  • Looking at the implied dependency chain: HomeController(IHomeService) -> HomeService(IServiceSearch) -> ServiceSearch(IMapper) -> ???? No part listed seems to implement IMapper that could be used to create an instance of ServiceSearch. – Monroe Thomas Apr 03 '15 at 04:33
  • @MonroeThomas...You're right I missed that. I've edited my post to reflect the IMapper implementation. I am still, unfortunately, still only hitting the default ctor, not the one with dependencies. – Big Daddy Apr 07 '15 at 12:38

1 Answers1

1

I managed to get your code working with these modifications:

  1. Move the types nested inside ServiceSearch outside of it. I don't think that MEF supports nested types. (Looks as though this is just a typo in the code sample above. I don't think it was intended.)

  2. Remove the InheritedExportAttribute from IMapper<,>. You have an explicit export on AccountMapper anyway. Without making this change, you end up with AccountMapper being exported twice. The import into ServiceSearch's constructor then fails because MEF doesn't know which of the two matching exports to use. Alternatively keep the InheritedExportAttribute and remove the explicit export.

  3. Either remove the InheritedExportAttribute on IHomeService or the ExportAttribute on HomeService, for the same reason as above.

Olly
  • 5,966
  • 31
  • 60
  • I'm not sure what you mean for #1. For 2 and 3, I thought that [Export] and [InheritedImport] are both required. Why is this wrong? – Big Daddy Apr 07 '15 at 16:02
  • `InheritedExportAttribute` automatically applies an export to all derived types. `ExportAttribute` exports just the type on which it appears. When you have both, the type ends up being exported twice. – Olly Apr 07 '15 at 18:21
  • Regarding #1, this may just be a typo in your code, but the `ServiceSearch` class doesn't have a closing "}" so when I copied your code into a new project for testing, I thought the following types (`IMapper<,>`, etc.) were supposed to be inside it. I think you can ignore #1. – Olly Apr 07 '15 at 18:23