I have several (eventually 100+) small DLL projects all based on MediatR. This means that the interfaces in use are just the IMediatR interfaces (IRequest<TResult>, IRequestHandler<IRequest<TResult>, TResult>). Since a lot of these do not have a UI and are called via orchestration from another DLL I was thinking I could create an Autofac Container project (DLL), register all the micro-services, then resolve what I need at runtime in another app that consumes my container. So far, so good.
Where I am running into problems is the registration of each and every CQRS handler. Right now, while everything is small in scope, they are being defined inline like this:
namespace My.Core.Container
{
public class CoreDependencies
{
#region Properties
public IMediator Mediator { get; private set; }
public IContainer Container { get; private set; }
private static ContainerBuilder _builder;
#endregion
#region Constructor
public CoreDependencies()
{
_builder = new ContainerBuilder();
// register MediatR types...
_builder.RegisterSource(new ContravariantRegistrationSource());
_builder.RegisterAssemblyTypes(typeof(IMediator).GetTypeInfo().Assembly).AsImplementedInterfaces();
_builder.Register<SingleInstanceFactory>(ctx =>
{
var c = ctx.Resolve<IComponentContext>();
return t => c.Resolve(t);
});
_builder.Register<MultiInstanceFactory>(ctx =>
{
var c = ctx.Resolve<IComponentContext>();
return t => (IEnumerable<object>)c.Resolve(typeof(IEnumerable<>).MakeGenericType(t));
});
// ################################################## //
// register EntityTree micro services...
_builder.RegisterAssemblyTypes(typeof(My.Core.EntityTree.GetChildren).GetTypeInfo().Assembly).AsImplementedInterfaces();
_builder.RegisterAssemblyTypes(typeof(My.Core.EntityTree.DeleteEntity).GetTypeInfo().Assembly).AsImplementedInterfaces();
_builder.RegisterAssemblyTypes(typeof(My.Core.EntityTree.AddEntity).GetTypeInfo().Assembly).AsImplementedInterfaces();
// register next micro services...
// register next micro services...
// ad naseum...
// ################################################## //
// Now build it...
Container = _builder.Build();
Mediator = Container.Resolve<IMediator>();
}
#endregion
}
}
So, my question is: How do I correctly do this registration? Right now, 2 or 3 "cores" (micro-services) but next month, 20, next year, 200, etc...
TIA
Instead of manually register assembly by assembly, you could do Assembly Scanning to retrieve all assemblies you need, and then, register them in simple loop (code not tested):
var assemblies = /* get assemblies based on project type (web/desktop) */;
foreach(var assembly in assemblies)
{
container.RegisterAssemblyTypes(assembly).AsImplementedInterfaces();
}
Btw, you should not expose your container as public property, unless you have very strong arguments to do so (service locator anti-pattern). Also SingleInstanceFactory and MultiInstanceFactory look pretty suspicious for me...
Related
Within my Web API I have linked Autofac as IoC container, and I do it like this:
Domain level
public class Autofac
{
protected ContainerBuilder Builder { get; set; }
public Autofac()
{
this.Builder = new ContainerBuilder();
}
public virtual IContainer Register()
{
// Register dependencies
SetUpRegistration(this.Builder);
// Build registration.
var container = this.Builder.Build();
// End
return container;
}
private static void SetUpRegistration(ContainerBuilder builder)
{
// === DATALAYER === //
// MyRepository
builder.RegisterType<MyRepository>()
.As<IMyRepository>()
.InstancePerLifetimeScope();
// === DOMAIN === //
// MyManager
builder.RegisterType<MyManager>()
.As<IMyManager>()
.InstancePerLifetimeScope();
}
}
Web API
public class Autofac : Domain.IoC.Autofac
{
public IContainer Register(HttpConfiguration config)
{
// Register your Web API controllers.
base.Builder.RegisterApiControllers(Assembly.GetExecutingAssembly());
// OPTIONAL: Register the Autofac filter provider.
base.Builder.RegisterWebApiFilterProvider(GlobalConfiguration.Configuration);
// Complete registration and get container instance.
var container = base.Register();
// Set the dependency resolver to be Autofac.
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
// Done.
return container;
}
}
As you see it inherits from the base class from Domain and sets up Web API specific config.
Usage
protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
GlobalConfiguration.Configure(WebApiConfig.Register);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
new IoC.Autofac().Register(GlobalConfiguration.Configuration);
}
Which is at global.asax, as you know.
The question
This works fine for Web API, but I haven't got a clue what I need to do to register all this within a UnitTest project context.
The idea is that I would create a similar implementation to the Autofac class at Web API level, but than with mocks (completely ignoring the base class from Domain).
Any pointers?
Personally I never see the need (and I struggle to comprehend how viable or helpful it would be) to setup my IoC container directly within a unit test.
As a unit test is used to test a logical piece of code that can be quickly built, easily ran and doesn't require much (I'd advocate no) tear-down. It should not require all of your application to be be setup for the test to run.
Remember that your unit test is simply testing the flow of data through the system i.e that your DomainManager is actually going to call a IRepository when you expect that it should. Then you would have separate test classes for all your repositories to determine that they would correctly add to the database etc.
I'm not sure how you use the DBContext class but as an example of a wrapper this is what it would sort of look like.
interface IDBSetWrapper
{
object Add(object entity);
}
interface IDBContextWrapper
{
...
IDBSet Set(Type entityType);
...
}
class DBContextWrapper : IDBContextWrapper
{
private readonly DBContext context;
public DBContextWrapper()
{
context = new DBContext();
}
...
public IDBSet Set(Type entityType)
{
var dbSet = context.Set(entityType);
return new DBSetWrapper(dbSet);
}
...
}
It's not much but I hope that it demonstrates what I mean about a thin wrapper. Basically the wrapper is the DBContext and will contain an instance of it within the class, the actual DBContext will be called when you request the wrapper to do anything.
I have shown what would happen when returning another object (in this case a DBSet), this will also be wrapped in a separate object with an interface. This is so that you can mock the returns from this class easily.
You can add this new wrapper into your IoC a little better now as it provides an interface.
One thing to note is that you won't be able to and probably wouldn't wish to test the wrapper class, there would be very little point as I see it. But previously I've seen colleagues do an integration test on these sort of classes.
I have two assemblies which implement the same interfaces (two different implementations for the same interface). When user logs into web forms application certain variable (flag) is being set to specific value. This variable should be used for loading implementations from one of these assemblies.
When application starts, I have the following code in Global.asax to register or known implementations - I have tried using Autofac and SimpeInjector:
// SimpleInjector
private static void Bootstrap()
{
var container = new Container();
// 2. Configure the container (register)
container.Register<IUserRepository, UserRepository>();
// 3. Store the container for use by Page classes.
Global.container = container;
// 4. Optionally verify the container's configuration.
// Did you know the container can diagnose your configuration?
// For more information, go to: https://bit.ly/YE8OJj.
container.Verify();
VerifyPages(container);
}
// Autofac
protected void Application_Start(object sender, EventArgs e)
{
BundleConfig.RegisterBundles(BundleTable.Bundles);
// Build up your application container and register your dependencies.
var builder = new ContainerBuilder();
builder.RegisterType<UserRepository>().As<IUserRepository>().InstancePerRequest();
// ... continue registering dependencies...
// Once you're done registering things, set the container
// provider up with your registrations.
_containerProvider = new ContainerProvider(builder.Build());
}
Now, after a user logs in, I need to register additional implementations, but from one of the two assemblies. I need to do this from code behind of login.aspx page, I believe.
Now I don't know if I should update the container by registering additional types somehow or if I can override some method of Autofac or SimpleInjector so when it tries to instantiate an implementation for an interface, I can point it to a specific assembly.
How could I implement this behavior? Please advise. Thanks.
What you need is some abstraction that allows you to request some contextual information for the user that allows you to base the decision of on which type to load. For instance:
public interface IUserContext
{
bool IsAdministrator { get; }
}
Here the Administator property is the thing that determines what types to load for the user. How to implement this class of course completely depends on how to store this information. Perhaps you retrieve this information from the database, or from a cookie, the session, what ever.
If you need an implementation that is depending on something that is ASP.NET specific (cookie, sessie, request), you will need to have an Web application specific implementation, such as:
public class AspNetUserContext : IUserContext
{
public bool IsAdministrator
{
get
{
return HttpContext.Current != null &&
(bool?)HttpContext.Current.Session["isadmin"] == true;
}
}
}
You can register this context using Simple Injector as follows:
container.Register<IUserContext, AspNetUserContext>();
Now if you have a certain abstraction where the implementations must differ based on this flag, you can register a factory delegate as follows:
container.Register<AdministratorUserRepository>();
container.Register<NormalUserRepository>();
container.Register<IUserRepository>(() =>
{
container.GetInstance<IUserContext>().IsAdministrator
? container.GetInstance<AdministratorUserRepository>()
: container.GetInstance<NormalUserRepository>();
});
Or better it would be to create some sort of composite proxy type that allows delegating to the actual repository:
public class AdminSelectableUserRepositoryProxy : IUserRepository
{
private readonly AdministratorUserRepository adminRepo;
private readonly NormalUserRepository normalRepo;
private readonly IUserContext userContext;
public AdminSelectableUserRepositoryProxy(
AdministratorUserRepository adminRepo,
NormalUserRepository normalRepo,
IUserContext userContext)
{
this.adminRepo = adminRepo;
this.normalRepo = normalRepo;
this.userContext = userContext;
}
public User GetById(Guid id)
{
return this.Repository.GetById(id);
}
private IUserRepository Repository
{
get
{
return this.userContext.IsAdministrator ? this.adminRepo : this.normalRepo;
}
}
}
Now the registration will can be simplified to the following:
container.Register<AdministratorUserRepository>();
container.Register<NormalUserRepository>();
container.Register<IUserRepository, AdminSelectableUserRepositoryProxy>();
When creating a StructureMap container, I typically do something like this:
var container = new Container(registry => {
registry.AddRegistry<MyRegistry>();
});
Where
public class MyRegistry : Registry {
public MyRegistry() {
Scan(x => {
x.Assembly("My.Assembly.Name");
x.RegisterConcreteTypesAgainstTheFirstInterface();
}
}
}
However, this has resulted in quite many registry.AddRegistry lines in a bootstrapper file, which is then copied into many projects. I would like to be able to call a method taking a constructed container and adding a registry to it, so I can modularize libraries.
I came up with this:
public static void Setup(ref Container container) {
container.PluginGraph.ImportRegistry(typeof(MyRegistry));
}
This works, in that the registry is properly added to the container (seen by calling container.WhatDoIHave() before and after), but it seems the actual mappings are not done - ie the interface IFoo is not registered to concrete class Foo that both are defined in My.Assembly.Name.
What is the difference in doing ImportRegistry and AddRegistry? Can my Setup method be fixed?
Did you try Container.Configure()? It exists to configure a container after it has already been initialized.
Let's say I have 5 separate assemblies with the following (assume the class name is different in each):
[Export(typeof(IService))]
public class Service: IService
{
// ...
}
And I have a class that will be a composite of these in my main assembly
public class CompositeService : IService
{
public CompositeService(IEnumerable<IService> services)
{
// ...
}
}
What I would like to do is have the Unity container resolve the CompositeService for the IService and have the MefContrib extension for Unity go and find the 5 other exports and inject them into CompositeService's constructor.
The problem is that you can't have N instances for a nameless unityContainer.RegisterType<IService> nor can you for named instances if they all have the same name.
I think I'm missing something simple in the combination of the 2 technologies (Unity + MEF) via the third (MefContrib) but can't seem to pick up on what it is.
Is this possible or is there a workaround? Eventually, I'm going for full bi-directional dependency injection and dynamic component discovery.
I think what is likely the best approach is to flip this around. Instead of trying to register your components via Unity, you actually leave the discovery of these parts to MEF. MEFContrib includes an Unity integration mechanism that allows your MEF composed parts to be injected into Unity components. This was original detailed at Piotr WŁodek's blog, whereby he also gives you a sample. Essentialy, the way it works is you can use a series of extension methods on your UnityContainer to register your catalogs. Internally, it will create the appropriate extension and wire up your container.
Here is a quick and dirty example, we'll create some interfaces:
public interface IUnityComponent
{
IEnumerable<IMefComponent> MefComponents { get; }
}
public interface IMefComponent
{
string Name { get; }
}
And then some sample parts which we'll export (via MEF):
[Export(typeof(IMefComponent))]
public class MefComponent1 : IMefComponent
{
public string Name { get { return "MEF Component 1"; } }
}
[Export(typeof(IMefComponent))]
public class MefComponent2 : IMefComponent
{
public string Name { get { return "MEF Component 2"; } }
}
Now, we'll create another part (this will be created via Unity):
public class UnityComponent : IUnityComponent
{
public UnityComponent(IEnumerable<IMefComponent> mefComponents)
{
// mefComponents should be provided from your MEF container.
MefComponents = mefComponents;
}
public IEnumerable<IMefComponent> MefComponents { get; private set; }
}
To wire it all up, we simply need to use the RegisterCatalog extension method on your UnityContainer (import MefContrib.Integration.Unity after you've added a reference to MEFContrib):
var container = new UnityContainer();
// Register the catalog - this handles MEF integration.
container.RegisterCatalog(new DirectoryCatalog("."));
// Register our Unity components.
container.RegisterType<IUnityComponent, UnityComponent>(new ContainerControlledLifetimeManager());
Now you should be able to grab the instance and enumerate the MEF-provided parts:
// Grab an instance of our component.
var instance = container.Resolve<IUnityComponent>();
foreach (var mefComponent in instance.MefComponents)
{
Console.WriteLine(mefComponent.Name);
}
note: 100% untested.
Just tried the same solution from Matthew here and it is working ok, Unity is picking up the exports from MEF and injecting them into the constructor (which accepts an IEnumerable<>).
Don't know if it can help you, but including both MefContrib and MefContrib.Integration.Unity can help: for a while I only had the latter included and encountered similar errors.
As a side note, keep in mind that all the registrations in Unity (coming from MEF exports) will be "nameless" so if you try ResolveAll<> you will get an empty collection and if you try Resolve<> you will get an exception if there is more than 1 implementation registered.
I have a project where my business layer is constructed using DI, but I'm trying to go an additional step and use Windsor to manage object construction.
Let's just say I have a pre-existing data layer (that I don't want to modify), that can be accessed via the following interface:
interface IDataFactory {
IDataService Service { get; }
}
A series of classes in my business layer depend on the services exposed through IDataFactory:
IFactory factory = DataFactory.NewFactory();
IBusinessService service = new ConcreteBusinessService(factory.Service);
I understand that in order to register IBusinessService to the Castle Windsor container, I'd use code similar to this:
IWindsorContainer container = new WindsorContainer();
container.AddComponent("businessService", typeof(IBusinessService), typeof(ConcreteBusinessService));
But for the life of me, I can't figure out how to register services from my data layer, using the my existing factory object. In essence, I'd like to say:
container.AddComponent("dataService", typeof(IDataService), factory.service);
Windsor seems to want me to say container.AddComponent("dataService", typeof(IDataService), typeOf(SomeConcreteDataService)), but in this instance, ConcreteDataService is internal to that assembly, and thus not accessible in mine.
How would I go about wiring up the data service, given that SomeConcreteDataService isn't known to my assembly?
This question is very similar to my own, except in my case, the AddComponent("calculator", typeof(ICalcService), typeof(CalculatorService), "Create"); call wouldn't work -- CalculatorService would be internal to another assembly, not available to the assembly wiring up the container.
Using Windsor 2.0:
[TestFixture]
public class WindsorTests {
public interface IDataService {}
public class DataService: IDataService {}
public interface IDataFactory {
IDataService Service { get; }
}
public class DataFactory: IDataFactory {
public IDataService Service {
get { return new DataService(); }
}
}
[Test]
public void FactoryTest() {
var container = new WindsorContainer();
container.AddFacility<FactorySupportFacility>();
container.AddComponent<IDataFactory, DataFactory>();
container.Register(Component.For<IDataService>().UsingFactory((IDataFactory f) => f.Service));
var service = container.Resolve<IDataService>();
Assert.IsInstanceOfType(typeof(DataService), service);
}
}
See the fluent API wiki page for more information.
Got it. The answer is, you don't need to worry about the implementation type:
IWindsorContainer container = new WindsorContainer();
container.AddFacility("factories", new FactorySupportFacility());
container.AddComponent("standard.interceptor", typeof(StandardInterceptor));
container.AddComponent("factory", typeof(DataFactory));
MutableConfiguration config = new MutableConfiguration("dataService");
config.Attributes["factoryId"] = "factory";
config.Attributes["factoryCreate"] = "get_Service";
container.Kernel.ConfigurationStore.AddComponentConfiguration("dataService", config);
container.Kernel.AddComponent("dataService", typeof(IDataService));
IDataService dataService = (IDataService) container["dataService"];
I had a "whoa" moment when I saw it execute successfully, because I hadn't passed in the specific implementation type to Kernel.AddComponent()