binks
binks

Reputation: 1033

Using MEF with MVC

I'm starting to use MEF with my MVC application, so that it follows SOLID priciples.

I asked this question last week: Should a dependency be injected many "levels" up than it is needed? and part of what I asked (in the comments) was, if you have two constructors;

One constructor for Dependancy Injection

Another construtor with no parameters

And the contstructor with no parameters instantiates instances of the dependancies needed, then this should make a Service Locator moot. The response was that a class should not instantiate it's own dependancies. OK, I get this, but looking at this MS tutorial on MEF:

http://msdn.microsoft.com/en-us/library/hh708870(v=vs.110).aspx

They say you should have two constructors:

 public HomeController() : this(new TraceLogger())
  {
  }

public HomeController(ILogger logger)
{
    _logger = logger;
}

But from what I've been told, the first constructor is a no-no as the class is instantiating it's own dependacy?

Also, in the tutorial, MS just say; replace the second construtor with this:

    public HomeController([Import("myTraceLogger")]ILogger logger)
    {
        _logger = logger;
    }

What's the point in that? I still have to supply an instance of of the ILogger... unless I'm missing something? I removed the default constructor:

 public HomeController() : this(new TraceLogger())
  {
  }

And the application just says: "No parameterless constructor defined for this object." So I must have to supply an instance, because if MEF was creating a new instance, surly it would work without a default constructor... and if not, what's the point in using MEF? I might as well just do the dependancy injection myself.

Upvotes: 2

Views: 361

Answers (2)

sarin
sarin

Reputation: 5307

OK. So you could use MEF to do Dependancy Injection and inject the parts, but personally I wouldn't. The performance i've seen on it is pretty dire. If you use it wrongly it can also leak and consume memory easily.

You can apply your solid principals with other techniques. Use a well know Inversion of Control (IoC) container, such as StructureMap or AutoFac. You can add the nuget package to your MVC app, write a few lines of setup code in the global asax and your constructors will automagically work. These are also much more forgiving and easier to setup and configure.

When you application starts up and creates the IoC container (or when the object is first requested depending on your settings), the dependency is 'Newed' up and injected into your class constructor. Effectively you don't need to do much other than tell the IoC container where to find an instance of a Logger class (i.e. in which assembly) if you class requests an ILogger.

public HomeController(ILogger logger)
{
    _logger = logger;
}

Check out these posts.

Upvotes: 1

mrtig
mrtig

Reputation: 2267

Sounds like you need to use [ImportingConstructor] attribute on your HomeController(ILogger) constructor. Like so:

[ImportingConstructor]
public HomeController([Import("myTraceLogger")]ILogger logger)
{
    _logger = logger;
}

MEF creates a singleton instance of ILogger (by default). It will make sure to create ILogger before it creates your HomeController class.

A service locator is convenient when you are creating a list of objects with exported types as part of some run-time workflow.

Upvotes: 2

Related Questions