Architecture Question: Services - c#

VS2K8, C#. I currently have a solution with the following projects:
Core - POCO domain objects and data interfaces
Data - Repository pattern. Implements the interfaces defined in Core. Also has the mapping classes for Fluent NHibernate.
Infrastructure - Used for dependency injection, configuring nhibernate, etc.
Tests - Tests [tests for Core, Data, etc.]
Web - MVC2 web project
Now, with that being said, I'm trying to determine the best course of action for adding things like: Joining a mailing list, a contact information submission, etc.
I don't believe these should be in web. And I don't think they need to be placed in Data, save for when saving the mailing list information and contact information, fwiw.
It sounds like this should be placed on the Core level. With that said, if placed in Core it would rely on saving to the database. I'm a bit perplexed on where to place this and how to architect it. What route what you guys take?
Is this something as simple as just creating an interface on the Core level called MailingList with a method called JoinMailingList(emailAddress), and then implementing that interface on Data? This doesn't sound like the best route as it's a business concern. Thoughts?

Add a services library and include service interfaces in your core library.
public interface IMailingListService
{
void Subscribe(string email);
void Unsubscribe(string email);
}
public interface IMailingListRepository
{
MailingList LoadMailingList();
void SaveMailingList(MailingList list);
}
public class MailingListService: IMailingListService
{
private IMailingListRepository _repository;
public MailingList(IMailingListRepository repository)
{
_repository = repository;
}
public void Subscribe(string email)
{
var list = _repository.LoadMailingList();
list.Subscribe(email);
_repository.SaveMailingList(list);
}
}

Related

Where dependency-injection registrations have to be put?

I've read the question Ioc/DI - Why do I have to reference all layers/assemblies in application's entry point?
So, in a Asp.Net MVC5 solution, the composition root is in the MVC5 project (and having a DependencyInjection assembly in charge of all the registrations does not make sense).
Within this picture, it is not clear to me what is the better approach among the following.
Approach 1
The concrete implementations are public class ... and all registrations clauses are centralized within the composition root (e.g. in one or more files under a CompositionRoot folder). MVC5 project must reference all the assemblies providing at least one concrete implementation to be bound. No library references the DI library. MVC project can contain interfaces to be bound with no drawbacks.
Approach 2
The concrete implementations are internal class .... Each library exposes a DI 'local' configuration handler. For example
public class DependencyInjectionConfig {
public static void Configure(Container container) {
//here registration of assembly-provided implementations
//...
}
}
which is up to register its own implementations. The composition root triggers registrations by calling all the Configure() methods, just one for each project. MVC5 project must then reference all the assemblies providing at least one concrete implementation to be bound. Libraries must reference the DI library. In this case, the MVC5 project cannot contain interfaces (otherwise there would be a circular reference): a ServiceLayer assembly would be needed to hold public interfaces to be bound.
Approach 3
Same as Approach 2, but local configuration modules are discovered dynamically through assembly reflection (by convention?). So MVC5 project has not to reference libraries. MVC project can contain interfaces and can be referenced by libraries. Libraries must reference the DI library.
What is the best practice here? Is there some other better possibility?
EDIT 1 (2016-12-22)
Thanks to received answers, I published this github project describing the best solution I found so far.
EDIT 2 (2018-09-09)
This answer provides an interesting option.
EDIT 3 (2020-12-29)
Finally, I came up with a complete solution, packaged in the form of a WebApi application template. I published this solution on GitHub HERE. This approach, not only gives a clear understanding about where DI rules have to be put, but also suggests to setup the application according to SOLID principles and CQRS pattern. The commit history of this project has been structured to have educational purposes.
EDIT 4 (2023-01-31)
The repository linked above publishes an article describing the solution as well.
I typically like to encapsulate these types of things into each project. So for example I might have the following. (This is an extremely simplified example, and I'll use the AutoFac in this example, but I'd imagine all DI frameworks have something like the following).
Common area for just POCOs and Interfaces.
// MyProject.Data.csproj
namespace MyProject.Data
{
public Interface IPersonRepository
{
Person Get();
}
public class Person
{
}
}
Implementation of Repositories and Data Access
// MyProject.Data.EF.csproj
// This project uses EF to implement that data
namespace MyProject.Data.EF
{
// internal, because I don't want anyone to actually create this class
internal class PersonRepository : IPersonRepository
{
Person Get()
{ // implementation }
}
public class Registration : Autofac.Module
{
protected override void Load(ContainerBuilder builder)
{
builder.Register<PersonRepository>()
.As<IPersonRepository>()
.IntancePerLifetimeScope();
}
}
}
Consumer
// MyPrject.Web.UI.csproj
// This project requires an IPersonRepository
namespace MyProject.Web.UI
{
// Asp.Net MVC Example
internal class IoCConfig
{
public static void Start()
{
var builder = new ContainerBuilder();
var assemblies = BuildManager.GetReferencedAssemblies()
.Cast<Assembly>();
builder.RegisterAssemblyModules(assemblies);
}
}
}
So the Dependencies look like:
MyProject.Data.csproj
- None
MyProject.Data.EF.csproj
- MyProject.Data
MyProject.Web.UI.csproj
- MyProject.Data
- MyProject.Data.EF
In this setup, the Web.UI cannot know anything about what is registered nor for what reason. It only knows that the EF project has implementations but can't access them.
I can drop EF for say Dapper extremely easily as each project encapsulates it's own implementations and registration.
If I was adding unit tests and had an InMemoryPersonRepository, how would I swap out the PersonRepository for my InMemoryPersonRepository?
Assuming we ignore any business logic layer and have an MVC Controller directly access our Data Accessor, my code might look like:
public class MyController
{
private readonly IPersonRepository _repo;
public MyController(IPersonRepository repo)
{
_repo = repo;
}
public IActionResult Index()
{
var person = _repo.Get();
var model = Map<PersonVM>(person);
return View(model);
}
}
Then a test using nSubstitute Might look like:
public class MyControllerTests
{
public void Index_Executed_ReturnsObjectWithSameId
{
// Assign
var repo = Substitute.For<IPersonRepository>();
var expectedId = 1;
repo.Get().Returns(new Person { Id = expected });
var controller = new MyController(repo);
// Act
var result = controller.Index() as ActionResult<PersonVM>;
// Assert
Assert.That(expectedId, Is.EqualTo(result.Value.Id));
}
You've identified a real problem. (One could say it's a good problem to have.) If entry application Areferences B, B references C, and B and/or C require some DI registration, that makes A (your entry application) responsible for knowing enough about the details of B and C to register all the dependencies.
The solution is to have a separate assembly that handles composing all of the registrations for B and C. A references that, and it provides all of the container configuration that A needs to use B and C.
The benefits are
A doesn't know more about B and C than it should
Neither A, B, nor C have to be tied to one particular DI framework like Unity or Windsor.
Here's an example. This is an event bus class that works best with a DI container. But in order to use it you shouldn't have to know all about the dependencies it needs to register. So for Windsor I created a DomainEventFacility. You just call
_container.AddFacility<DomainEventFacility>();
and all of the dependencies are registered. The only thing you register are your event handlers.
Then if I want to use the same event bus library with a different DI container like Unity I can just create some similar assembly to handle the same configuration for Unity.

ServiceStack multiple implementations of same interface in Funq.Container

In ServiceStack application, I have Funq configured to inject a session per request like this:
container.Register<NHibernate.ISessionFactory>(sessionFactoryForDB1);
container.Register<NHibernate.ISession>(c => c.Resolve<NHibernate.ISessionFactory>()
.OpenSession())
.ReusedWithin(Funq.ReuseScope.Request);
My service looks like this, and it works just fine:
public class MyNhAwareService : Service
{
public ISession Session { get; set; }
public object Any(DoSomething request)
{
...
}
}
Now, the problem comes in when I want to add a second NHibernate database into the mix with its own session factory:
container.Register<NHibernate.ISessionFactory>(sessionFactoryForDB1);
container.Register<NHibernate.ISession>(c => c.Resolve<NHibernate.ISessionFactory>()
.OpenSession())
.ReusedWithin(Funq.ReuseScope.Request);
// add a different session factory
container.Register<NHibernate.ISessionFactory>(sessionFactoryForDB2);
I've been experimenting with a variety of ways Funq can be used, and I thought I had found the way forward when I discovered the 'RegisterNamed()" method, but that still doesn't help, as I can't use anything except TryResolve() from within my service.
This seems like it should be possible, but I'm beating my head against the wall trying to work it out...Any advice would be greatly appreciated.
You have a couple ways of going about this.
Option 1: Unique Interfaces
This option is to create a distinct interface for each NHibernate database so that they can be uniquely resolved by Funq.
For example:
interface FactoryA : NHibernate.ISessionFactory
{
}
interface FactoryB : NHibernate.ISessionFactory
{
}
You could then proceed as you are now. The same applies for the session. See here for a little more detail about the process:
How to register multiple IDbConnectionFactory instances using Funq in ServiceStack.net
Option 2: Named Instance
This option I am less familiar with, but you can name your instances using Funq:
container.Register<NHibernate.ISessionFactory>("FactoryA",sessionFactoryForDB1);
And then in your service, resolve it thusly:
ServiceStackHost.Instance.Container.ResolveNamed<NHibernate.ISessionFactory>("FactoryA");
This option uses Service Location, which I personally find less attractive.

Combine WindowsAuthentication with rules stored in DB

I have an ASP.NET MVC5 application that uses WindowsAuhhentication to authenticate the user. Now I need to add a security layer to this application and would like to base this on the standard MVC security model and use the AuthorizeAttribute. This relies on User.IsInRole, but currently this will return the groups that the user belongs to. I do not want to have to store roles as groups in the AD, instead I would like to just have the roles for each user stored in my DB.
So the question is, how do I override the IsInRole method in the WindowsPrincipal, or can I create a CustomPricipal that does what I want?
I have found lots of information on similar topics but most of them seem to reference MVC4 and from what I can gather the entire security model has changed between MVC4 and MVC5. So what is the best way of doing that now?
All help and pointers much appreciated.
Cheers Mike
P.S. And if anyone has any idea how to best incorporate EF, IOC and caching into this then that would be great.
I have found MVC5 Asp.Identity to be really developer friendly compared to the old membership provider... which might be the reason there is a lack of documentation at this time. It is actually intuitive.
If your authentication rules reside in a database EntityFramework will convert stored procedures into Complex Types. After you do that you could create an 'AuthenticationService' service layer and use DI to inject the complex types into Asp.Identity as needed.
To customize Asp.Net Identity all you have to do is add properties to IdentityModels.cs and AccountViewModels.cs, by default Asp.Identity uses the ApplicationDbContext which you have to do absolutely nothing to configure.
In addition, you can access the users information in a similar manner to User.IsInRole.
OK, this is what I have done. I would really like peoples feedback as to best practice and improvements I could make.
I created a new Principal derived from WindowsPrincipal and with an overridden IsInRole Method.
public class QSDPrincipal : WindowsPrincipal
{
private readonly IUserService userService;
public QSDPrincipal(WindowsIdentity ntIdentity,
IUserService userService) :
base(ntIdentity)
{
this.userService = userService;
}
public override bool IsInRole(string role)
{
return userService.CurrentUserIsInRole(role);
}
}
This uses DI to populate the userService object that lives in my BL layer. So I had to configure the container to build this properly.
container.RegisterType<WindowsIdentity>(new HierarchicalLifetimeManager(),
new InjectionFactory(x => (WindowsIdentity)HttpContext.Current.User.Identity));
container.RegisterType<IPrincipal, QSDPrincipal>(new HierarchicalLifetimeManager());
The I use the DependencyResolved to create my new Principal in the PostAuthenticateRequest event.
protected void Application_PostAuthenticateRequest(object sender, EventArgs e)
{
var newUser = (IPrincipal)DependencyResolver.Current.GetService(typeof(IPrincipal));
HttpContext.Current.User = newUser;
}
Then in the UserService itself I implement a method and implement some simple caching so it only makes one DB query per request.
public bool CurrentUserIsInRole(string role)
{
return CurrentUserRoles.Contains(role);
}
private IEnumerable<string> currentUserRoles;
public IEnumerable<string> CurrentUserRoles
{
get
{
if (currentUserRoles == null)
{
var user = GetCurrentUser();
currentUserRoles = new List<string>
{
user.Role.Name
};
}
return currentUserRoles;
}
}
And that is it and it all seems to work.
Thoughts and improvements much appreciated.
Cheers Mike

How-to inject the Entity Framework DbContext into the ConfigurationBasedRepository of SharpRepository

I really would like to use SharpRepository together with Ninject, but I do not understand how to configure Ninject to share the Entity Framework DbContext between the repositories.
I am using Entity Framework version 5 and Ninject version 3.
Currently I am using Ef5Repository in my source code, but I want to replace it with ConfigurationBasedRepository. But I cannot figure out how to pass (or inject) the EF DbContext to the repositories.
Example (current state):
using SharpRepository.Repository;
public interface IProductRepository : IRepository<Product>
{
}
using SharpRepository.Ef5Repository;
using System.Data.Entity;
// TODO Tightly coupled to Ef5Repository.
public class ProductRepository : Ef5Repository<Product>, IProductRepository
{
// TODO The DbContext has to be injected manually.
public ProductRepository(DbContext context) : base(context)
{
}
// [...]
}
Goal:
using SharpRepository.Repository;
public interface IProductRepository : IRepository<Product>
{
}
public class ProductRepository : ConfigurationBasedRepository<Product, int>, IProductRepository
{
// [...]
}
I've already read the two blog posts SharpRepository: Getting Started and SharpRepository: Configuration, but they both do not help me, since:
The used DIC is StructureMap, not Ninject.
The source code examples are incomplete (e.g. usage of not declared variables).
So my question: Can someone provide me with some source code example how-to to achieve the goal described above (sharing one Entity Framework DbContext instance between all repositories extending ConfigurationBasedRepository)?
First, you will need to install the SharpRepository.Ioc.Ninject NuGet package. There are extension methods in here for hooking up Ninject to handle the loading a generic repository and setting the dependency resolver that SharpRepository uses.
Where ever you are setting up your Ninject binding rules (all the calls to kernel.Bind<>), you will need to add:
kernel.BindSharpRepository();
Next, in your Global.asax, or App_Start code, or your Bootstrapper logic (where ever you are calling application startup code) you will need to add the following:
// kernel is the specific kernel that you are setting up all the binding for
RepositoryDependencyResolver.SetDependencyResolver(new NinjectDependencyResolver(kernel));
This will tell SharpRepository to use this Ninject Kernel when getting a new DbContext.
The last thing to do is to setup the rules for binding for the DbContext itself. If you are in a web application you will most likely want the scope of the DbContext to be per request. I personally don't use Ninject but I found this reference for using InRequestScope. I believe your code would look something like this:
kernel.Bind<DbContext>().To<MyCustomEfContext>().InRequestScope().WithConstructorArgument("connectionString", ConfigurationManager.ConnectionStrings["MyCustomEfContext"].ConnectionString);
Most people won't need this next piece but if you have custom logic in your CustomEfContext (I have an override for logging on calls to SaveChanges() for example), then you'll need to define your custom context type in the configuration file like so:
<repositories>
<repository name="ef5Repository" connectionString="CustomEfContext" cachingStrategy="standardCachingStrategy" dbContextType="My.Data.CustomEfContext, My.Data" factory="SharpRepository.Ef5Repository.Ef5ConfigRepositoryFactory, SharpRepository.Ef5Repository" />
</repositories>
Where dbContextType defines the type of the custom DbContext you are using using the full type, namespace syntax. If you do this then you'll need to set Ninject to Bind on the custom context by changing .Bind<DbContext>() to .Bind<CustomEfContext>(). But like I said normally you can use DbContext directly without an issue.
First of all, the solution provided in the answer by Jeff T works!
I will conclude the steps I took to make Ninject work in a ASP.NET MVC 4 + EF 5 project. It is important to mention that the Specific Repository pattern is implemented via SharpRepository in the following example.
Required software
Install Ninject and "Ninject.MVC3" (which also installs "Ninject.Web.Common") via NuGet.
Install SharpRepository, "SharpRepository for EF5" and "SharpRepository with Ninject IOC" via NuGet.
Define the Repository layer
Create a DbContext derived class, e.g. Domain.EfContext. It is the
"recommended way to work with context".
Declare all required DbSet<T> as public properties, e.g. public DbSet<Product> Products { get; set; }
Declare the following two constructors in the class Domain.EfContext:
public EfContext() : base() {}
public EfContext(string connectionName) : base(connectionName) {}
Define an interface for the Specific Repository, e.g.:
// TODO By extending IRepository, the interface implements default Create-Read-Update-Delete (CRUD) logic.
// We can use "traits" to make the repository more "specific", e.g. via extending "ICanInsert".
// https://github.com/SharpRepository/SharpRepository/blob/master/SharpRepository.Samples/HowToUseTraits.cs
public interface IProjectRepository : IRepository<Project>
{
// TODO Add domain specific logic here.
}
Define a class which is implementing the Specific Repository and inherits from SharpRepository.Repository.ConfigurationBasedRepository<T, TKey>, e.g.:
public class ProductRepository : ConfigurationBasedRepository<Product, int>, IProductRepository
{
// TODO Implement domain specific logic here.
}
Define the Consumer layer
Create a Controller, e.g. Controllers.ProductController.
public class ProductController : Controller
{
private IProductRepository Repository { get; private set; }
// TODO Will be used by the DiC.
public ProductController(IProductRepository repository)
{
this.Repository = repository;
}
}
Set up Dependency Injection (DI) via the Dependency Injection Container (DiC) Ninject
The file App_Start/NinjectWebCommon.cs is automatically created by Ninject.Web.Common and we can load our modules and register our services in the method RegisterServices(IKernel kernel) : void of the class NinjectWebCommon.
Here is the complete source code of that method for the example:
private static void RegisterServices(IKernel kernel)
{
kernel.BindSharpRepository();
RepositoryDependencyResolver.SetDependencyResolver(
new NinjectDependencyResolver(kernel)
);
string connectionString = ConfigurationManager.ConnectionStrings["EfContext"].ConnectionString;
kernel.Bind<DbContext>()
.To<EfContext>()
.InRequestScope()
.WithConstructorArgument("connectionString", connectionString);
kernel.Bind<IProductRepository>().To<ProductRepository>();
}
Define the following sharpRepository section in the Web.config:
<sharpRepository>
<repositories default="ef5Repository">
<repository name="ef5Repository"
connectionString="EfContext"
cachingStrategy="standardCachingStrategy"
dbContextType="Domain.EfContext, Domain"
factory="SharpRepository.Ef5Repository.Ef5ConfigRepositoryFactory, SharpRepository.Ef5Repository"
/>
</repositories>
</sharpRepository>
In addition, the connectionStrings section to make the example complete (I am using SQL Server LocalDB).
<connectionStrings>
<add name="EfContext" providerName="System.Data.SqlClient" connectionString="Data Source=(localdb)\v11.0;Initial Catalog=Domain;Integrated Security=True" />
</connectionStrings>
I hope that this conclusion helps other people to get ASP.NET MVC 4 together with Entity Framework 5 and SharpRepository up and running!
Please leave me a reply if I took one or more unnecessary steps or if you see possibilities to improve the architecture described in the example.
Btw, I had to add the dbContextType attribute to the repository section to make it work (in contrast to the answer of Jeff T).
EDIT (2013-08-28): Striked out unnecessary steps (not required with the latest version of SharpRepository).

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