Need guidance on Autofac custom lifetimescopes vs. multi tenancy - c#

Scenario:
I need to provide different interface implementations to the same interface definitions within the same web application (appdomain) but to different "scopes".
Imagine a simple hierarchical web content structure like this (if you are not familiar with SharePoint):
RootWeb (SPSite) (ctx here)
|______SubWeb1 (SPWeb) (ctx here)
|______SubWeb2 (SPWeb)
|______SubWeb3 (SPWeb)
|_______SubWeb3.1 (SPWeb) (ctx here)
|_______SubWeb3.2 (SPWeb)
RootWeb, SubWeb1 und SubWeb3.1 provide Contexts. That is I implemented an AppIsolatedContext class that is specific for a certain hierarchy level. If a level does not provide a context it inherits the context from the parent node and so on. For example SubWeb3 would inherit its context from RootWeb. SubWeb3.1 however provides its own isolated context.
The isolated context is merely a static ConcurrentDictionary.
Okay so far so good. Now regarding Autofac (I'm new to Autofac and any other DI container - not to the principle of IoC though)... I'm not sure how I correctly set it up to dispose of objects correctly. Actually it shouldn't be that much of an issue because the objects are (once they are created) are supposed to live until the appdomain gets recycled (think of them as a "per isolated context singleton").
I'd be inclined to do something like that:
// For completeness.. a dummy page which creates a "dummy" context
public partial class _Default : Page
{
private static AppIsolatedContext _dummyContainer = new AppIsolatedContext();
public _Default()
{
_dummyContainer.ExceptionHandler.Execute("Test Message");
}
}
// The isolated context which holds all the "context" specific objects
public class AppIsolatedContext
{
public static IContainer Container { get; set; }
public IExceptionHandler ExceptionHandler { get; set; }
//public ISomething Something { get; set; }
//public ISomethingElse SomethingElse { get; set; }
public AppIsolatedContext()
{
// set up autofac
// Create your builder.
ContainerBuilder builder = new ContainerBuilder();
// Usually you're only interested in exposing the type
// via its interface:
builder.RegisterType<MailNotificationHandler>().As<INotificationHandler>();
builder.RegisterType<ExceptionHandler>().As<IExceptionHandler>();
Container = builder.Build();
using (ILifetimeScope scope = Container.BeginLifetimeScope())
{
ExceptionHandler = scope.Resolve<IExceptionHandler>();
//Something = scope.Resolve<ISomething>();
//SomethingElse = scope.Resolve<ISomethingElse>();
}
}
}
Of course my application is not limited to these "context singleton" instances. I will have per request lifetime instances too.. but that's what the ASP.NET integration modules are there for right? I hope they can seamlessly be integrated in SharePoint (2013) too :)
So my question is is it okay what I proposed or do I need to get my hands dirty? If so some direction would be phenomenal...
Digging through Autofac's documentation I stumbled across its multi tenancy capability.
I believe this might suit my purpose as well.. can anyone confirm this?
using System;
using System.Web;
using Autofac.Extras.Multitenant;
namespace DemoNamespace
{
public class RequestParameterStrategy : ITenantIdentificationStrategy
{
public bool TryIdentifyTenant(out object tenantId)
{
tenantId = AppIsolatedContext.Current.Id; // not implemented in the dummy class above, but present in the real thing.
return !string.IsNullOrWhiteSpace(tenantId);
}
}
}
If anything is not crystal - please don't hesitate to tell me :)

Disclaimer: This is a fairly non-trivial question, and given that and my somewhat lack of familiarity with SharePoint 2013, I'll do my best to answer but you'll need to adapt the answer somewhat to your needs.
The way I would structure this is with named lifetime scopes. Rather than contexts with their own containers, use a hierarchy of named scopes. This is how the multitenant support works; it's also how ASP.NET per-web-request support works.
You will first want to read the Autofac wiki page on instance scopes as well as this primer on Autofac lifetimes. Neither of these are small articles but both have important concepts to understand. Some of what I explain here will only make sense if you understand lifetime scope.
Lifetime scopes are nestable, which is how you share singletons or instance-per-web-request sorts of things. At the root of the application is a container with all of your registrations, and you spawn scopes from that.
Container
Child scope
Child of child scope
In a more code related format, it's like this:
var builder = new ContainerBuilder();
var container = builder.Build();
using(var child = container.BeginLifetimeScope())
{
using(var childOfChild = child.BeginLifetimeScope())
{
}
}
You actually resolve components out of scopes - the container itself is a scope.
Key things about lifetime scopes:
You can name them, allowing you to have "singletons" within a named scope.
You can register things on the fly during the call to BeginLifetimeScope.
This is how the multitenant support for Autofac works. Each tenant gets its own named lifetime scope.
Unfortunately, the multitenant support is one-level: Application container spawns tenant-specific "root" scopes, but that's it. Your site hierarchy where you have these contexts has more than one level, so the multitenant support isn't going to work. You can, however, potentially look at that source code for ideas.
What I'd be doing is naming scopes at each level. Each site would get passed an ILifetimeScope from which it can resolve things. In code, it'll look a little like:
var builder = new ContainerBuilder();
// RootWeb will use the container directly and build its per-web-request
// scope from it.
var container = builder.Build();
// Each sub web will get its own scope...
using(var sw1Scope = container.BeginLifetimeScope("SubWeb"))
{
// Each child of the sub web will get a scope...
using(var sw11Scope = sw1Scope.BeginLifetimeScope("SubWeb"))
{
}
using(var sw12Scope = sw1Scope.BeginLifetimeScope("SubWeb"))
{
}
}
Note I'm tagging each level of sub-web scope as "SubWeb" - that will allow you to have "instance per sub web" sort of registrations in both container-level and sub-web-level registrations.
// Register a "singleton" per sub-web:
builder.RegisterType<Foo>()
.As<IFoo>()
.InstancePerMatchingLifetimeScope("SubWeb");
Now, obviously, that's a conceptual thing there - you won't actually be able to wrap everything in using statements like that. You'll need to manage your creation and disposal differently because creation will happen in a different place than disposal.
You can look at both the ASP.NET and multitenant source to get ideas on how to do that. The general algorithm will be:
At application startup, build the root container.
As sub webs start up, spawn a nested lifetime scope named for the sub web.
If a sub web needs a specific component registered, do that during the call to BeginLifetimeScope
If you need the "context" at each sub web level, you'd pass it the scope created for that sub web rather than creating a whole separate container.
Now, you could take it another step by keeping a root-level dictionary of sub web ID to scope so that you'd not need per-level "context" objects at all. It'd be more like a DependencyResolver.Current.GetService<T> kind of pattern. If you look at how the MultitenantContainer in the Autofac multitenant support works, you'll see a similar sort of tenant-ID-to-scope dictionary.
In fact, that multitenant support will be a good pattern to look at, especially if you also want to have per-web-request scopes. The Autofac ASP.NET support requires you pass in a parent ILifetimeScope from which child web request lifetime scopes will be spawned. The multitenant support adds some dynamic aspect in there so when the ASP.NET support calls BeginLifetimeScope the multitenant portion of things automatically figures out (through tenant identification) which tenant should be the parent of the current request. You could do the same thing with your hierarchy of sub-webs. However, again, the multitenant support is a flat structure while your sub webs are a hierarchy, so the multitenant support won't just work.
This is all a long way of saying you have an interesting use case here, but you're going to be getting your hands pretty dirty.

Related

Microsoft Dependency Injection Documentation

In the documentation for dependency injection I notice the following line.
The MVC framework will automatically look at the service provider to
register our dependency in the Controller.
They then provide a basic example with constructor injection, not their example but in essence this.
public class Example
{
private IFooFactory foo;
public Example(IFooFactory foo) => this.foo = foo;
public void SampleUse()
{
using(var context = foo.Create())
context.DoSomething();
}
}
If you have a console application, by default it will not look at the service provider to register your dependency with the concrete implementation. Is there a way to simulate that? Otherwise the console application will require you to do something along these lines:
public static Main(string[] args)
{
// Stuff to prepare the application and build service provider.
var service = serviceProvider.GetService<IFooFactory>();
using(var context = service.Create())
context.DoSomething();
// OR
var fooFactory = serviceProvider.GetService<IFooFactory>();
new Example(fooFactory).SampleUse();
}
Which creates the problem of having to pass IFooFactory or pulling things into the main that you may wanted separated for structure. How can I make the console application look at the provider when a new class is created with a defined interface?
You have to create everything manually as the framework is not there to automagically do it for you.
var services = new ServiceCollection();
services.AddTransient<IFooFactory, FooFactory>();
services.AddTransient<Example>();
IServiceProvider serviceProvider = services.BuildServiceProvider();
Example example = serviceProvider.GetService<Example>();
example.SampleUse();
While not ideal, it is usually the way shown in most examples where DI is configured manually.
When you inspect the framework DI integration, behind the scenes it does the exact same thing during startup.
You could probably write your own code to inspect available types, but that is a very broad task to tackle on your own.
Reference Dependency injection in ASP.NET Core
Default service container replacement
The built-in service container is meant to serve the needs of the
framework and most consumer apps. We recommend using the built-in
container unless you need a specific feature that it doesn't support.
Some of the features supported in 3rd party containers not found in
the built-in container:
Property injection
Injection based on name
Child containers
Custom lifetime management
Func<T> support for lazy initialization

Unity Dependency Injection - How to create the instance to be injected at runtime

Trying to implement Dependency Injection in an ASP.Net Web API project.
I would like to be able to inject an instance of Account into some of my services.
The Account instance should be created with the users Guid and this is not known until runtime.
So in my service I have:
public TransactionService(Account acc)
{
_account = acc;
}
And in my application startup I can do this - where container is a new UnityContainer:
container.RegisterType<Instanet.Engine.Account>(new InjectionConstructor(new Guid("xxxxxx")));
This, of course, isn't any good as it would be using the same Account for every user/request etc.
If I try to use something like :
container.RegisterType<Instanet.Engine.Account>(new InjectionConstructor(GetTheUsersID()));
... where GetTheUsersID() needs to either examine a cookie or the ASP.Net Identity request it's of course not available in the app startup.
So - Where/How (in simple terms please, this DI stuff is hurting my brain) do I implement this so I can inject an instanced Account into any of the services that may need it.
You generally don't want to mix state and behavior for components that get resolved via the container--DI should be used for components that can be modeled as pure services.
That said, sometimes it makes sense to wrap global or context-specific state in a service component.
In your case, if you only need the UserId locally in a one or more services (in other words, not passing it from one service to another). You mentioned being able to get the UserId from a cookie, so maybe it would look something like:
public class CookieService : ICookieService
{
public int GetCurrentUserId()
{
//pseudo code
return HttpContext.Current.GetCookie["UserId"];
}
}
Now you can inject ICookieService where a UserId is needed.
More complex cases may require an Abstract Factory:
http://blog.ploeh.dk/2012/03/15/ImplementinganAbstractFactory/
If there is only one Account instance possible for the session, then I would create an Account instance in the bootstrap code before all your services are running.
Then you can populate the guid and all other data in your account instance, and register the initialized instance of Account class in Unity via container.RegisterInstance method.
Later it will resolve to what you need.
Does it help?

is there another way of changing Database Instance in Autofac

I have an application that use multiple Database.
i found out i can change that by using the connection builder. like so :
var configNameEf = "ProjectConnection";
var cs = System.Configuration.ConfigurationManager.ConnectionStrings[configNameEf].ConnectionString;
var sqlcnxstringbuilder = new SqlConnectionStringBuilder(cs);
sqlcnxstringbuilder.InitialCatalog = _Database;
but then i need to change the autofac Lifescope of UnitOfWork so that it will now redirect the request to the good Database instance.
what i found out after quite a while is that i can do it like this from a DelegatedHandler :
HttpConfiguration config = GlobalConfiguration.Configuration;
DependencyConfig.Register(config, sqlcnxstringbuilder.ToString());
request.Properties["MS_DependencyScope"] = config.DependencyResolver.GetRequestLifetimeScope();
The question is, is there any other way to do that, that change the MS_DependencyScope parametter of the request. This solution work but i think it is kind of shady.
here is the registry in DependencyConfig:
public static void Register(HttpConfiguration config, String bdContext = null)
{
var builder = new ContainerBuilder();
builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
builder.Register(_ => new ProjectContext(bdContext)).As<ProjectContext>().InstancePerApiRequest();
builder.RegisterType<UnitOfWork>().As<IUnitOfWork>().InstancePerApiRequest();
// Register IMappingEngine
builder.Register(_ => Mapper.Engine).As<IMappingEngine>().SingleInstance();
config.DependencyResolver = new AutofacWebApiDependencyResolver(builder.Build());
config.DependencyResolver.BeginScope();
}
The way the question is described and the way the answer to my comment sounds, you have the following situation:
The application uses per-request lifetime units of work. I see this from your registrations.
Only one database is used in the application at a given point in time. That is, each request doesn't have to determine a different database; they all use the same one until the connection string changes. This is seen in the way the database is retrieved from using a fixed application setting.
The connection string in configuration may change, at which point the database used needs to change.
Assuming I have understood the question correctly...
If the app setting is in web.config (as it appears), then changing the string in web.config will actually restart the application. This question talks about that in more detail:
How to prevent an ASP.NET application restarting when the web.config is modified?
If that's the case, you don't have any work to do - just register the database as a singleton and when the web.config changes, the app restarts, re-runs the app startup logic, gets the new database, and magic happens.
If the app setting is not in web.config then you should probably create a project context factory class.
The factory would serve as the encapsulation for the logic of reading configuration and building the connection to the database. It'll also serve as the place to cache the connection for the times when the setting hasn't changed.
The interface would look something like this:
public interface IProjectContextFactory
{
ProjectContext GetContext();
}
A simple implementation (without locking, error handling, logging, and all the good stuff you should put in) might be:
public class ProjectContextFactory : IProjectContextFactory
{
private ProjectContext _currentContext = null;
private string _currentConnectionString = null;
private const string ConnectionKey = "ProjectConnection";
public ProjectContext GetContext()
{
// Seriously, don't forget the locking, etc. in here
// to make this thread-safe! I'm omitting it for simplicity.
var cs = ConfigurationManager.ConnectionStrings[ConnectionKey].ConnectionString;
if(this._currentConnectionString != cs)
{
this._currentConnectionString = cs;
var builder = new SqlConnectionStringBuilder(cs);
builder.InitialCatalog = _Database;
this._currentContext = new ProjectContext(builder.ToString());
}
return this._currentContext;
}
}
OK, now you have a factory that caches the built project context and only changes it if the configuration changes. (If you're not caching the ProjectContext and are, instead, caching the database connection string or something else, the principle still holds - you need a class that manages the caching and checking of the configuration so the change can happen as needed.)
Now that you have a cache/factory, you can use that in your Autofac registrations rather than a raw connection string.
builder.RegisterType<ProjectContextFactory>()
.As<IProjectContextFactory>()
.SingleInstance();
builder.Register(c => c.Resolve<IProjectContextFactory>().GetContext())
.As<ProjectContext>()
.InstancePerRequest();
The ProjectContext will now change on a per request basis when the configured connection string changes.
Aside: I see odd stuff going on with the request lifetime scope. I see in your registration that you're creating your own request lifetime scope. With this method you shouldn't have to do that. If, however, you find that you still need to (or want to), you need to make sure both the originally-created lifetime scope and the one you created are disposed. Lifetime scopes do not get automatically disposed and do hang onto object references so they can handle disposal. There is a high probability that if you're not handling this properly then you have a subtle memory leak. The Autofac Web API integration will take care of creation and disposal of the request lifetime for you, but if you change out the request lifetime, odd things are going to happen.

Unity -- using information from request to resolve dependencies

I've recently refactored my MVC application to use Unity dependency injection to resolve dependencies, which is great. It's much more decomposable, etc., etc.
What I'm doing now is adding the capability for multiple tenants to use it. The approach I'm using (so that the rest of the code doesn't have to know much about the tenants) is creating things like a tenant-filtered version of my repository interface (which is just a proxy for another repository... so it will call one of the underlying methods, then check if the record has the right tenant and behave accordingly). This lets me basically emulate having a totally separate store for each tenant even though under the hood the data is not segregated, so relatively little of the client code needs to change.
The problem with all of this is how it fits into the DI way of doing things. What I'm planning to do is, at the beginning of the request, detect the host name, then use that to determine the tenant (each tenant will have a list of hostnames in the DB). Although I'm using per-request lifetimes for most objects Unity is constructing and resolving I don't really get how Unity can "know" what tenant to use since it would need both the data about the request (which I suppose the controller will have, but I don't think is available in my container configuration method) and access to the database to know which host (and it hardly seems desirable to have my container configuration making database calls). I can solve #2 by only passing in a host name and making the classes with tenants go figure out which tenant is being referenced, but that doesn't help with #1.
Right now I'm using "property injection" (also known as "a public property" in less high-falutin' circles), but I don't see how I'm going to avoid having my controller be the one that actually feeds the tenant data in, so now I don't really have just the one composition root controlling everything.
Is there a way I can do this in the composition root, or should I just resign myself to having the controller do this work?
For some reason you seem to forget about injection factories. Registering interface/type against a factory lets you execute arbitrarily complicated code upon resolving, including consulting the request, tenant database, whatever.
container.RegisterType<IRepository>(
new InjectionFactory(
c => {
// whatever, consult the database
// whatever, consult the url
return ...;
} );
The factory composition is transparent so that whenever you need it, the target doesn't even know that the factory code has been executed rather than a type instance from simple mapping.
Somewhere it needs to make a database call. Maybe the simplest place would be in global.ascx if it's needed system wide.
private static ConcurrentDictionary<string, string> _tenantCache = new ConcurrentDictionary<string, string>();
protected virtual void Application_BeginRequest(object sender, EventArgs e)
{
HttpApplication app = (HttpApplication)source;
var tenantId = _tenantCache.GetOrAdd(app.Context.Request.Url.Host, host =>
{
// Make database call in this class
var tenant = new TenantResolver();
return tenant.GetTenantId(host);
})
app.Context.Items["TenantID"] = tenantId ;
}
You will want to cache the result as Application_BeginRequest is called alot. You can then configure Unity to have child containers. Put all the common/default mappings in the parent container then create a child container per tenant and register the correct implementation for each tenant in it's own child container.
Then implement IDependencyResolver to return the correct child container.
public class TenantDependencyResolver : IDependencyResolver
{
private static IUnityContainer _parentContainer;
private static IDictionary<string, IUnityContainer> _childContainers = new Dictionary<string, IUnityContainer>();
public TenantDependencyResolver()
{
var fakeTenentID = "localhost";
var fakeTenentContainer = _parentContainer.CreateChildContainer();
// register any specific fakeTenent Interfaces to classes here
//Add the child container to the dictionary for use later
_childContainers[fakeTenentID] = fakeTenentContainer;
}
private IUnityContainer GetContainer()
{
var tenantID = HttpContext.Current.Items["TenantID"].ToString();
if (_childContainers.ContainsKey(tenantID)
{
return _childContainers[tenantID];
}
return _parentContainer;
}
public object GetService(Type serviceType)
{
var container = GetContainer();
return container.Resolve(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
var container = GetContainer();
return container.ResolveAll(serviceType);
}
}
Then set ASP.NET MVC DependecyResolver to be the TenantDependencyResolver. I didn't run this code but it should give you an idea of what you would need to do. If your implementations are set then you might be able to do it in the static constructor of TenantDependecyResolver.

Proper use of [Import] attribute in MEF

I'm learning MEF and I wanted to create a simple example (application) to see how it works in action. Thus I thought of a simple translator. I created a solution with four projects (DLL files):
Contracts
Web
BingTranslator
GoogleTranslator
Contracts contains the ITranslate interface. As the name applies, it would only contain contracts (interfaces), thus exporters and importers can use it.
public interface ITranslator
{
string Translate(string text);
}
BingTranslator and GoogleTranslator are both exporters of this contract. They both implement this contract and provide (export) different translation services (one from Bing, another from Google).
[Export(typeof(ITranslator))]
public class GoogleTranslator: ITranslator
{
public string Translate(string text)
{
// Here, I would connect to Google translate and do the work.
return "Translated by Google Translator";
}
}
and the BingTranslator is:
[Export(typeof(ITranslator))]
public class BingTranslator : ITranslator
{
public string Translate(string text)
{
return "Translated by Bing";
}
}
Now, in my Web project, I simply want to get the text from the user, translate it with one of those translators (Bing and Google), and return the result back to the user. Thus in my Web application, I'm dependent upon a translator. Therefore, I've created a controller this way:
public class GeneralController : Controller
{
[Import]
public ITranslator Translator { get; set; }
public JsonResult Translate(string text)
{
return Json(new
{
source = text,
translation = Translator.Translate(text)
});
}
}
and the last piece of the puzzle should be to glue these components (parts) together (to compose the overall song from smaller pieces). So, in Application_Start of the Web project, I have:
var parts = new AggregateCatalog
(
new DirectoryCatalog(Server.MapPath("/parts")),
new DirectoryCatalog(Server.MapPath("/bin"))
);
var composer = new CompositionContainer(parts);
composer.ComposeParts();
in which /parts is the folder where I drop GoogleTranslator.dll and BingTranslator.dll files (exporters are located in these files), and in the /bin folder
I simply have my Web.dll file which contains importer. However, my problem is that, MEF doesn't populate Translator property of the GeneralController with the required translator. I read almost every question related to MEF on this site, but I couldn't figure out what's wrong with my example. Can anyone please tell me what I've missed here?
OK what you need to do is (without prescribing for performance, this is just to see it working)
public class GeneralController : Controller
{
[Import]
public ITranslator Translator { get; set; }
public JsonResult Translate(string text)
{
var container = new CompositionContainer(
new DirectoryCatalog(Path.Combine(HttpRuntime.BinDirectory, "Plugins")));
CompositionBatch compositionBatch = new CompositionBatch();
compositionBatch.AddPart(this);
Container.Compose(compositionBatch);
return Json(new
{
source = text,
translation = Translator.Translate(text)
});
}
}
I am no expert in MEF, and to be frank for what I use it for, it does not do much for me since I only use it to load DLLs and then I have an entry point to dependency inject and from then on I use DI containers and not MEF.
MEF is imperative - as far as I have seen. In your case, you need to pro-actively compose what you need to be MEFed, i.e. your controller. So your controller factory need to compose your controller instance.
Since I rarely use MEFed components in my MVC app, I have a filter for those actions requiring MEF (instead of MEFing all my controllers in my controller facrory):
public class InitialisePluginsAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
CompositionBatch compositionBatch = new CompositionBatch();
compositionBatch.AddPart(filterContext.Controller);
UniversalCompositionContainer.Current.Container.Compose(
compositionBatch);
base.OnActionExecuting(filterContext);
}
}
Here UniversalCompositionContainer.Current.Container is a singleton container initialised with my directory catalogs.
My personal view on MEF
MEF, while not a DI framework, it does a lot of that. As such, there is a big overlap with DI and if you already use DI framework, they are bound to collide.
MEF is powerful in loading DLLs in runtime especially when you have WPF app where you might be loading/unloading plugins and expect everything else to work as it was, adding/removing features.
For a web app, this does not make a lot of sense, since you are really not supposed to drop a DLL in a working web application. Hence, its uses are very limited.
I am going to write a post on plugins in ASP.NET MVC and will update this post with a link.
MEF will only populate imports on the objects which it constructs itself. In the case of ASP.NET MVC, it is ASP.NET which creates the controller objects. It will not recognize the [Import] attribute, so that's why you see that the dependency is missing.
To make MEF construct the controllers, you have to do the following:
Mark the controller class itself with [Export].
Implement a IDependencyResolver implementation which wraps the MEF container. You can implement GetService by asking the MEF container for a matching export. You can generate a MEF contract string from the requested type with AttributedModelServices.GetContractName.
Register that resolver by calling DependencyResolver.SetResolver in Application_Start.
You probably also need to mark most of your exported parts with [PartCreationPolicy(CreationPolicy.NonShared)] to prevent the same instance from being reused in several requests concurrently. Any state kept in your MEF parts would be subject to race conditions otherwise.
edit: this blog post has a good example of the whole procedure.
edit2: there may be another problem. The MEF container will hold references to any IDisposable object it creates, so that it can dispose those objects when the container itself is disposed. However, this is not appropriate for objects with a "per request" lifetime! You will effectively have a memory leak for any services which implement IDisposable.
It is probably easier to just use an alternative like AutoFac, which has a NuGet package for ASP.NET MVC integration and which has support for per-request lifetimes.
As #Aliostad mentioned, you do need to have the composition initialise code running during/after controller creation for it to work - simply having it in the global.asax file will not work.
However, you will also need to use [ImportMany] instead of just [Import], since in your example you could be working with any number of ITranslator implementations from the binaries that you discover. The point being that if you have many ITranslator, but are importing them into a single instance, you will likely get an exception from MEF since it won't know which implementation you actually want.
So instead you use:
[ImportMany]
public IEnumerable<ITranslator> Translator { get; set; }
Quick example:
http://dotnetbyexample.blogspot.co.uk/2010/04/very-basic-mef-sample-using-importmany.html

Categories

Resources