There is a ImportingConstructor atribute where you can annotate on the constructor, but why will we use it?
From the StackOverflow (Why use ImportingConstructor, from JaredPar), it has the following lines
Quote:
The problem with using [Import] is that it separates the creation of an object into two distinct and observable phases: created and initialized. Where [ImportingConstructor] allows this to remain as a single phase exactly as it would for every other .Net object.
This difference becomes observable in a number of ways
- Adding a new [Import] on a field changes the logical contract of a type. Yet it doesn't change the public or usage contract. This means any code which previously compiled will continue to compile even though the objects dependencies have changed (think unit tests). This takes what should be a compile time error and makes it a runtime one
- Code Contracts are unusable if you have an [Import]. The contract verification engine properly recognizes that all fields can exist as null values and will require a check before every use of a field.
- Even though your object can logically have fields which are set an init time and never reset you can't express this with readonly as you would with a normal C# object
and Mathew Abbott has this:
In terms of MEF, you can get away with using [Import] instead of [ImportingConstructor] as MEF will throw an exception when it cannot satisfy all imports on a type, and will only return the type after both initialisation ([ImportingConstructor]) and then [Import]s.
Constructor injection is generally preferable.
So here is the code that you can compare for yourself why to use ImportingConstructor..
using System;
using System.ComponentModel.Composition;
using System.ComponentModel.Composition.Hosting;
using log4net;
using log4net.Core;
namespace ImportingConstructorDemo
{
class Program
{
static void Main(string[] args)
{
System.Diagnostics.Debugger.Break();
var batch = new CompositionBatch();
CompositionContainer container;
var reflectionCatalog = new AssemblyCatalog(System.Reflection.Assembly.GetExecutingAssembly());
var extensionPath = System.IO.Path.Combine(Environment.CurrentDirectory, "extensions");
if (System.IO.Directory.Exists(extensionPath))
{
var directoryCatalog = new DirectoryCatalog(extensionPath);
var defaultCatalogEp = new CatalogExportProvider(reflectionCatalog);
container = new CompositionContainer(directoryCatalog, defaultCatalogEp);
defaultCatalogEp.SourceProvider = container;
}
else
container = new CompositionContainer(reflectionCatalog);
container.Compose(batch);
//var service1 = container.GetExportedValue<MyService>();
//var service2 = container.GetExportedValue<MyService2>();
}
}
[Export]
public class MyService
{
[Import]
public ILog Logger { get; set; }
public void SaySomething()
{
Logger.Info("Something");
}
}
[Export]
public class MyService2
{
private readonly ILog _logger;
[ImportingConstructor]
public MyService2(ILog logger)
{
if (logger == null) throw new ArgumentNullException("logger");
_logger = logger;
}
public void SaySomething()
{
_logger.Info("Sometihng else");
}
}
}