I have encountered a problem while using Moq (v4.8.1) in a factory method for Castle.Windsor (v4.1.0). I would like to know if anyone else has encountered this, and what they did to solve it.
I have a simple interface defined as:
interface IFoo
{
Task DoFooAsync(Bar bar);
}
In my main project I register the following in my WindsorContainer:
container
.Register(Component.For<IFoo, Foo>()
.LifestyleTransient());
This resolves nicely at runtime.
In my test project I do the following:
container.Register(Component.For<IFoo>().UsingFactorymethod(() => {
var mock = new Mock<IFoo>();
mock
.Setup(x => x.DoFooAsync(It.IsAny<Bar>()))
.Returns(() => Task.FromResult(true));
return mock.Object;
})
.IsDefault());
This fails during test with the message from Castle.MicroKernel.ComponentActivator.AbstractComponentActivator.ApplyCommissionConcerns(Object instance):
"Can not apply commission concerns to component Late Bound MyAssembly.IFoo because it appears to be a target-less proxy. Currently those are not supported."
Note: The 'IsDefault()' is only there to make Castle.Windsor override the registration from the main project, and it is not related to this problem (I tried running without it and the problem persists).
If I instead do the following:
// exact same code as above, just placed outside the factory method
var mock = new Mock<IFoo>();
mock
.Setup(x => x.DoFooAsync(It.IsAny<Bar>()))
.Returns(() => Task.FromResult(true));
// different registration
container
.Register(Component.For<IFoo>()
.Instance(mock.Object).IsDefault());
Then everything works. But now my IFoo instance is reused each time IFoo is resolved - which is a different behavior than in my main project, and therfore not desired.
I have looked into the Castle.Windsor code to understand what is going on, but without real success.
Moq internally uses Castle's dynamic proxy and mocked class is in fact proxy generated by Castle and that's what for some internal reasons Castle's developers don't want to support. You can read about it more here:
https://github.com/castleproject/Windsor/issues/224
https://github.com/castleproject/castle-youtrack-export/blob/master/IOC/IOC-332.xml
So as Nkosi already commented, you should rather think about what you really need to achieve and reconsider your design.
"my IFoo instance is reused each time IFoo is resolved - which is a different behavior than in my main project, and therfore not desired."
What about creating a property with a lambda? Something like:
private IFoo TheMock => CreateMock();
private IFoo CreateMock()
{
var mock = new Mock<IFoo>();
mock
.Setup(x => x.DoFooAsync(It.IsAny<Bar>()))
.Returns(() => Task.FromResult(true));
return mock.Object;
}
And then register it
container
.Register(Component.For<IFoo>()
.Instance(TheMock).IsDefault());
Disclaimer: Haven't tested that, because I do not use Castle.Windsor.
This works for me. UsingFactoryMethod() was failing. It uses Nsubstitute for fake injection.
var blobservice = Substitute.For<IBlobFileService>();
RegisterFakeServiceInstance(blobservice);
private void RegisterFakeServiceInstance<TService>(TService fakeService) where TService : class
{
IocManager.IocContainer.Register(
Component.For<TService>()
.Instance(fakeService)
.LifestyleSingleton()
);
}
Related
I have a DataAccess class which takes a string as a parameter:
public class DataAccess : IDataAccess
{
public DataAccess(string connectionString)...
}
public DataAccessModule : Module
{
protected override void Load(ContainerBuilder builder) => builder.RegisterType<DataAccess>().As<IDataAccess>();
}
I publish that as a couple of nuget packages (one for the DataAccess class, one for the Module).
In my client I have ConfigReader class which reads a config, which is where I get the connection string from.
public DataAccessModule : Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterType<ConfigReader>().As<IConfigReader>();
builder.Register(c => c.Resolve<IConfigReader>().Read()).As<Config>();
}
}
Now I need to pass the connection string as a parameter to the IDataAccess.
Note that I never resolve the IDataAccess - its a parameter of some other classes.
What I want to do is Register the parameter, but I can't see that autofac allows me to do that.
The following wont work either as it leads to infinite recursion:
builder.Register(c => {
var config = c.Resolve<Config>();
return c.Resolve<IDataAccess>(new Parameter(typeof(string), config.ConnectionString));
});
Before I get going, there are a couple of relevant docs you may want to check out in detail:
Passing Parameters to Register
FAQ: How do I inject configuration, environment, or context parameters?
It looks like you got partway there, but let's see what we can do.
First, it doesn't matter that things are in different modules. Once it all ends up in the container it doesn't matter where it's coming from. That's sort of a red herring thrown into the question title.
Given that, let's boil this down:
// Original registrations, not the solution
builder.RegisterType<ConfigReader>().As<IConfigReader>();
builder.Register(c => c.Resolve<IConfigReader>().Read()).As<Config>();
builder.Register(c => {
var config = c.Resolve<Config>();
return c.Resolve<IDataAccess>(new Parameter(typeof(string), config.ConnectionString));
});
Next thing I'd recommend is to always be explicit in delegate registrations. (That's actually one of the documented best practices.) It helps with the perf, but it also helps see things more clearly. Given that, let's update a little.
// Being specific with the lambda registration.
builder.RegisterType<ConfigReader>().As<IConfigReader>();
builder.Register(c => c.Resolve<IConfigReader>().Read()).As<Config>();
builder.Register(c => {
var config = c.Resolve<Config>();
return c.Resolve<IDataAccess>(new Parameter(typeof(string), config.ConnectionString));
}).As<IDataAccess>();
Now it's clear why the infinite recursion happens (this is where I got sort of stuck reading quickly) - you're trying to resolve the same thing you're registering (as you noted in the comments). So... you have to unwind that (as I mentioned in the comments).
What you want is DataAccess to be the IDataAccess. So, somewhere in there you need to either register DataAccess as IDataAccess or otherwise tell Autofac how to create that.
One way to do that is to just new it up in the lambda. That's how the FAQ shows it in the sample.
// New-up DataAccess in the lambda.
builder.RegisterType<ConfigReader>().As<IConfigReader>();
builder.Register(c => c.Resolve<IConfigReader>().Read()).As<Config>();
builder.Register(c => {
var config = c.Resolve<Config>();
return new DataAccess(config.ConnectionString);
}).As<IDataAccess>();
Now, you could get fancier with it, but I'm a big fan of keeping it simple. If this is all you need, call it good.
But... let's say you're really, really trying to get all the parameters into Autofac registrations and there's a reason you don't want to new it up.
Using ResolvedParameter can do it all without a lambda.
// Resolved parameters all the way!
builder.RegisterType<ConfigReader>().As<IConfigReader>();
builder.Register(c => c.Resolve<IConfigReader>().Read()).As<Config>();
builder
.RegisterType<DataAccess>()
.As<IDataAccess>()
.WithParameter(
new ResolvedParameter(
(pi, ctx) => pi.ParameterType == typeof(string) && pi.Name == "connectionString",
(pi, ctx) => ctx.Resolve<Config>().ConnectionString));
The two docs I linked above have more examples and information. There are more ways to do this, but this is just a couple. I know the docs are a little long, but it would be worth taking the time to read them through. Good luck!
You might want to reconsider any dependencies on Autofac in the library. Users of the library might want to use a different DI tool.
I would turn the dependency on the string into a dependency on an interface that provides the connection string and let the client inject an implementation of that interface.
We have components registrations in Castle Windsor container like so
void RegisterComponent<TInterface, TImplementation>() {
var component = Component.For<TInterface>().ImplementedBy<TImplementation>();
component.Interceptors<SomeInterceptor>();
container.Register(component);
}
However we got to the problem that when we do a method call from within the class it does not get intercepted. For example we have component like
ServiceA : IService {
public void MethodA1() {
// do some stuff
}
public void MethodA2() {
MethodA1();
}
}
And if we call MethodA2 or MethodA1 methods from some other class it is intercepted, but MethodA1 apparently not intercepted when called from MethodA2 since the call is from within the class.
We have found similar case with the solution Castle Dynamic Proxy not intercepting method calls when invoked from within the class
However the solution features component and proxy creation using new operator which is not suitable in our case since we are using container. Can we use this solution with component registration like above? Or are there other approaches to solve the problem?
For interception to work on MethodA1 when invoked from MethodA2 you need to be using inheritance based interception (it's because you are using this reference to make the invocation).
To make inheritance based interception possible first you need to make MethodA1 and MethodA2 virtual.
Then you can make container registration like this:
container.Register(Component.For<ServiceA>().Interceptors<SomeInterceptor>());
container.Register(Component.For<IService>().UsingFactoryMethod(c => c.Resolve<ServiceA>()));
First register your service as itself applying interceptors (this will add inheritance based interception over the service). Then you can register the interface which will use service registered earlier.
Change your registration to the following and Windsor should switch to class proxies - i.e. using inheritance for interception, instead of composition.
void RegisterComponent<TInterface, TImplementation>() {
container.Register(Component.For<TInterface,TImplementation>().ImplementedBy<TImplementation>().Interceptors<SomeInterceptor>());
}
We use CreateClassProxy method to create the proxy for the service as it was proposed in an answer to the question Castle Dynamic Proxy not intercepting method calls when invoked from within the class.
Then we register the obtained proxy as an implementation for the interface.
So our custom RegisterComponent method looks like this
private void RegisterComponent<TInterface, TImplementation>()
where TInterface : class
where TImplementation : class, TInterface
{
var proxyType = new ProxyGenerator().CreateClassProxy<TImplementation>().GetType();
Container.Register(Component.For<TInterface>().ImplementedBy(proxyType));
}
The full component registration is
Container = new WindsorContainer();
Container.Kernel.Resolver.AddSubResolver(new CollectionResolver(Container.Kernel));
// Interceptor
Container.Register(Component.For<IInterceptor>().ImplementedBy<SomeInterceptor>().LifestyleTransient());
// Component registrations
RegisterComponent<ISomeService, SomeService>();
And, of course, all methods you need to intercept should be virtual since inheritance based proxy is used.
However a drawback of this solution is that you could not use constructor injection when creating a proxy object.
Notice that you are creating "dummy" proxy object with new operator only to get a type of the proxy. Therefore you are unable to use constructor injection only when constructing a dummy proxy, but when you resolve your service via container, injection would work just fine. So this drawback is critical only for components with construction logic being more complex than just assigment of dependencies. If you need only dependency assigments you can try to resolve all dependencies from container manually before creating dummy proxy
private object[] ResolveConstructorParameters<TType>()
{
return typeof(TType).GetConstructors()
.Single(c => c.IsPublic)
.GetParameters()
.Select(p => _container.Resolve(p.ParameterType))
.ToArray();
}
and then RegisterComponent would become
private void RegisterComponent<TInterface, TImplementation>()
where TInterface : class
where TImplementation : class, TInterface
{
var constructorParameters = ResolveConstructorParameters<TImplementation>();
var proxyType = new ProxyGenerator().CreateClassProxy(typeof(TImplementation), constructorParameters).GetType();
_container.Register(Component.For<TInterface>().ImplementedBy(proxyType));
}
You can also just fill arguments with null.
#NikolayKondratyev I've looked into https://github.com/castleproject/Windsor/blob/master/src/Castle.Windsor/Windsor/Proxy/DefaultProxyFactory.cs#L110
and I've done the registration the easy way:
container.Register(Classes.FromThisAssembly().BasedOn(typeof(IRepositoryBase<,>))
.WithServiceAllInterfaces().WithServiceSelf()
.LifestyleTransient());
Note .WithServiceSelf() call, this actually switches class-based proxying
I know this is an old thread, but I just came across it while getting Castle interceptors working in Blazor WASM (which they actually do, but beware...Mono can't seem to support proxying any class that has any generic methods...).
Anyway, to get around this issue in my case, I simply injected the container into my class, and in the method that needed to call a "sibling method" via this I simply resolved a fresh instance of my interface and called the method on that. It won't work for scenarios with shared context/transient states, but the interceptor indeed does its thing.
In Blazor's client WASM app's Program.cs:
public static async Task Main(string[] args)
{
WebAssemblyHostBuilder builder = WebAssemblyHostBuilder.CreateDefault(args);
...
builder.ConfigureContainer<IWindsorContainer>(new WindsorServiceProviderFactory(), container =>
{
container.Register(Component.For<IInterceptor>()
.ImplementedBy<BlazorInterceptor>()
.Named("BlazorInterceptor").LifestyleTransient());
});
...
builder.Services.AddScoped<IService, Service>();
...
await builder.Build().RunAsync();
}
Example service and interface implementation:
public Interface IService
{
MethodA(int arg);
MethodB(int arg);
}
[Interceptor("BlazorInterceptor")]
public class Service : IService
{
private readonly IServiceProvider _container;
public Service(IServiceProvider container)
{
this._container = container;
}
public MethodA(int arg)
{
IService service = this._container.GetRequiredService<IService>();
service.MethodB(arg);
}
public MethodB(int arg)
{
//should be intercepted...just in a different instance of the service unless you're using singletons...
}
}
Pros: Doesn't require virtualizing methods or complicating your DI configuration.
Cons: Kind of gross (useful for stateless repositories, but would probably give something like EF a heart attack).
I use a self-made "external" library to get some basic infrastructure in place when creating new web-applications. I recently made some changes to how my repositories work and came across this warning from Simple Injector Diagnostic Warnings:
SimpleInjector.DiagnosticVerificationException : The configuration is
invalid. The following diagnostic warnings were reported:
-[Torn Lifestyle] The registration for IUnitOfWork maps to the same implementation and lifestyle as the registrations for IUnitOfWork,
IUnitOfWork, IUnitOfWork and IUnitOfWork do. They all map to
EmptyUnitOfWork (Singleton). This will cause each registration to
resolve to a different instance: each registration will have its own
instance. See the Error property for detailed information about the
warnings. Please see https://simpleinjector.org/diagnostics how to fix
problems and how to suppress individual warnings.
The core assembly of my library has an empty implementation of IUnitOfWork called EmptyUnitOfWork which is just a simple no-op class:
internal sealed class EmptyUnitOfWork : IUnitOfWork
{
public void SaveChanges()
{
// Do nothing
}
}
This class is then registered in the container when there is no other unit of work avaliable. I do this by using the container.ResolveUnregisteredType(...) like so:
// Register an EmptyUnitOfWork to be returned when a IUnitOfWork is requested:
container.ResolveUnregisteredType += (sender, e) =>
{
if (e.UnregisteredServiceType == typeof(IUnitOfWork))
{
// Register the instance as singleton.
var registration = Lifestyle.Singleton.CreateRegistration<IUnitOfWork, EmptyUnitOfWork>(container);
e.Register(registration);
}
};
First time I've used above method - but works fine with this test:
[Fact]
public void RegistersEmptyUnitOfWork_AsSingleton_WhenIUnitOfWorkIsNotRegisted()
{
var instance = _container.GetInstance<IUnitOfWork>();
var registration = _container.GetRegistration(typeof (IUnitOfWork));
Assert.NotNull(instance);
Assert.IsType<EmptyUnitOfWork>(instance);
Assert.Equal(Lifestyle.Singleton, registration.Lifestyle);
}
Now for the fun part, I have an extension method in a supporting library which registers an EntityFramework IUnitOfWork if my application needs one:
public static void RegisterEntityFramework<TContext>(this Container container) where TContext : DbContext
{
if (container == null)
throw new ArgumentNullException(nameof(container));
var lifestyle = Lifestyle.CreateHybrid(() =>
HttpContext.Current != null,
new WebRequestLifestyle(),
new LifetimeScopeLifestyle()
);
container.Register<DbContext, TContext>(lifestyle);
container.Register<IUnitOfWork, EntityFrameworkUnitOfWork>(lifestyle);
container.Register(typeof (IRepository<>), typeof (EntityFrameworkRepository<>), lifestyle);
}
But somehow this throws the warning from Simple Injector - but I just injected the EntityFrameworkUnitOfWork so the EmptyUnitOfWork should not be triggered?
The reason for this design is that I have a CommandTransactionDecorator in my core library which uses the IUnitOfWork to save changes. I just want to have an empty one if a IUnitOfWork is not required by the application.
For reference this is the decorator:
internal sealed class CommandTransactionDecorator<TCommand> : IHandleCommand<TCommand> where TCommand : ICommand
{
private readonly IUnitOfWork _unitOfWork;
private readonly Func<IHandleCommand<TCommand>> _handlerFactory;
public CommandTransactionDecorator(IUnitOfWork unitOfWork, Func<IHandleCommand<TCommand>> handlerFactory)
{
_unitOfWork = unitOfWork;
_handlerFactory = handlerFactory;
}
public void Handle(TCommand command)
{
_handlerFactory().Handle(command);
_unitOfWork.SaveChanges();
}
}
UPDATE
It seems like this is the registration that makes the warning:
var registration = Lifestyle.Singleton.CreateRegistration<IUnitOfWork, EmptyUnitOfWork>(container);
e.Register(registration);
Changing it to e.Register(() => new EmptyUnitOfWork()); makes the warning go away, but then the lifestyle is not singleton?
What you are seeing is that ResolveUnregisteredType is called multiple times. This causes multiple singleton registrations for the same type to be made. Each registration gets its own instance. This will result in an application that consists of multiple instances of that type, which is usually not what you want to happen when you register a type as singleton. Since your EmptyUnitOfWork doesn't have any behavior, there is probably no problem, but Simple Injector can obviously not guess that this is the case, so it throws an exception.
What you are experiencing however is a breaking change / bug that was introduced in Simple Injector v3. In Simple Injector v1 and v2 the resulting registration of a ResolveUnregisteredType was cached; which meant that a call to Verify() would trigger your custom delegate just once. In Simple Injector v3.0 however, the resulting registration isn't cached anymore. This was an oversight, that has slipped through. The idea was to make ResolveUnregisteredType context aware. To be context aware, caching was not an option anymore. So caching was removed, but we eventually decided not to make ResolveUnregisteredType context aware, while we forgot to add the caching again.
The funny thing of this accidental behavior however is, that it expose a bug in your code. This bug already existed even when you used v2, but v3 now (accidentally) slaps you in the face with it. With v2, the correctness of your registration depended on the use of the Verify() method. Verify() builds all object graphs on a single thread. Without the use of Verify() however, the object graphs are compiled lazily and in case you are running a multi-threaded application, multiple threads can simultaneously call ResolveUnregisteredType; Simple Injector never locked ResolveUnregisteredType and this is documented.
So the result of this is that without a call to Verify() you could still end up in multiple registrations of that specific component, which of course again could lead to really ugly hard to find problems, that usually only appear once in a way in production.
This is how you should actually write that registration:
Lazy<Registration> registration = new Lazy<Registration>(() =>
Lifestyle.Singleton.CreateRegistration<IUnitOfWork, EmptyUnitOfWork>(container));
container.ResolveUnregisteredType += (sender, e) => {
if (e.UnregisteredServiceType == typeof(IUnitOfWork)) {
e.Register(registration.Value);
}
};
With Simple Injector v3 however, you hardly ever have to use the ResolveUnregisteredType event anymore. You can do make the following registration instead:
container.RegisterConditional<IUnitOfWork, EntityFrameworkUnitOfWork>(Lifestyle.Scoped,
c => true);
// NOTE: This registration must be made second
container.RegisterConditional<IUnitOfWork, EmptyUnitOfWork>(Lifestyle.Singleton,
c => !c.Handled);
This solves the problem of having to think about multi-threading completely. Here we make two conditional registrations, where the first is always applied (using the predicate c => true). You might be tempted to make the first registration unconditional using Register<IUnitOfWork, EFUoW>(), but that won't work, because Simple Injector will detect that the second registration can never be applied and an exception will be thrown. So the use of the c => true predicate suppresses this detection. I wouldn't usually advice such construct, because it blinds Simple Injector. In your case however it seems reasonable, because both registrations are made at different moment.
I now will have to think about whether or not I want to change this behavior in v3 and do caching. Advantage of caching is that it can improve performance, but the downside is that it hides bugs.
I am currently using Simple Injector for the first time. In my .NET project I am running test and mocking data returned from a web service and registering the object to the container like so
_container.Register<IWebServiceOrder>(() => mock.Object, Lifestyle.Transient);
This works fine. But in my tests I want to test the behavior of the system on a second call to the web service that will contain updated data, so the mock object will need to be updated.
By default Simple Injector does not allow Overriding existing registrations but the official website states it is possible to change this behavior like below.
https://simpleinjector.readthedocs.org/en/latest/howto.html#override-existing-registrations
container.Options.AllowOverridingRegistrations = true;
Unfortunately i still get an error when i try to register the object a second time even with the above code.
The container can't be changed after the first call to GetInstance, GetAllInstances and Verify
Any ideas on why this is happening?
Replacing an existing registration after you already worked with the container hardly ever has the behavior you would expect (and this holds for all DI libraries) and that's the reason why the Simple Injector container is locked. This is described in more details here (as #qujck already pointed out).
First of all, if you are writing unit tests, you shouldn't use a container at all. Your unit tests should create the class under test themselves, or you extract this logic to a convenient factory method, such as:
private static MailNotifier CreateMailNotifier(
IDeposit deposit = null, ISendMail mailSender = null, ILog logger = null)
{
return new MailNotifier(
deposit ?? Substitute.For<IDeposit>(),
mailSender ?? Substitute.For<ISendMail>(),
logger ?? Substitute.For<ILog>());
}
This factory method is a variation to the Test Data Builder pattern.
By making use of optional parameters, it allows the unit test to specify only the fake implementation it requires during testing:
public void Notify_WithValidUser_LogsAMessage()
{
// Arrange
var user = new User();
var logger = new FakeLogger();
MailNotifier sut = CreateMailNotifier(logger: logger);
// Act
sut.Notify(user);
// Assert
Assert.AreEqual(expected: 1, actual: logger.LoggedMessages.Count);
}
If you use a container, because creating the class under test by hand is too cumbersome, it indicates a problem in your class under test (most likely a Single Responsibility Principle violation). Prevent using tools to work around problems in your design; your code is speaking to you.
For integration tests however, it is much more usual to use the container, but in that case you should simply create a new container for each integration test. This way you can add or replace the IWebServiceOrder without any problem.
I am trying to rewrite my app from a service pattern to a command and query pattern (before I move to CQRS). Currently I'm stuck on this blog.
It shows where he moved unit of work commit from the base command into a PostCommitCommandHandlerDecorator, then use Simple Injector to bind them up. The writer also stated that not all commands will require the use of unit of work, which is true in my case because not every command talks to a database but some send emails, etc.
How do I architect my commands and bindings in such a way that only those commands that are required to be wrapped in a unit of work commit will be bound as such by the IoC container?
How do I architect my commands and bindings in such a way that only those commands that are required to be wrapped in a unit of work commit will be bound as such by the IoC container?
First of all, does that really matter that not all handlers use the unit of work? Is it a problem when a unit of work is created, while it isn’t used? Because when there are no performance problems, there’s no need to make your code more complicated.
But let’s assume that it does matter. In that case, the trick is to query the container whether the unit of work is injected somewhere. You can make use of Lazy<T> to get this working. Take a look at the following registration:
Func<IUnitOfWork> uowFactory =
() => new MyUnitOfWork(connectionString);
// Register the factory as Lazy<IUnitOfWork>
container.Register<Lazy<IUnitOfWork>>(
() => new Lazy<IUnitOfWork>(uowFactory),
Lifestyle.Scoped);
// Create a registration that redirects to Lazy<IUnitOfWork>
container.Register<IUnitOfWork>(
() => container.GetInstance<Lazy<IUnitOfWork>>().Value,
Lifestyle.Scoped);
For the rest of the article I assume you're building a web application, but the idea will be the same.
With this registration, when the container resolves an object graph with a component that depends on IUnitOfWork, under the covers it will resolve the Lazy<IUnitOfWork> and get its value. We cache the Lazy<IUnitOfWork> per request, so this allows us to have another component that depends on Lazy<IUnitOfWork> and check its IsValueCreated property to see if the IUnitOfWork was injected anywhere.
Now your decorator could look like this:
public class TransactionCommandHandlerDecorator<TCommand>
: ICommandHandler<TCommand>
{
private readonly ICommandHandler<TCommand> decorated;
private readonly Lazy<IUnitOfWork> lazyUnitOfWork;
public TransactionCommandHandlerDecorator(
ICommandHandler<TCommand> decorated,
Lazy<IUnitOfWork> lazyUnitOfWork)
{
this.decorated = decorated;
this.lazyUnitOfWork = lazyUnitOfWork;
}
public void Handle(TCommand command)
{
this.decorated.Handle(command);
if (this.lazyUnitOfWork.IsValueCreated)
{
this.lazyUnitOfWork.Value.SubmitChanges();
}
}
}
Note however that you still don’t know whether the unit of work is actually used or not, but I think it’s safe to assume that the unit of work will be used when it gets injected. You don’t want to inject an unused dependency.
If that doesn’t cut it, and you want to check whether it is created, you will have to inject a proxy unit of work that allows you to check this. For instance:
public class DelayedUnitOfWorkProxy : IUnitOfWork
{
private Lazy<IUnitOfWork> uow;
public DelayedUnitOfWorkProxy(Lazy<IUnitOfWork> uow)
{
this.uow = uow;
}
void IUnitOfwork.SubmitChanges()
{
this.uow.Value.SubmitChanges();
}
// TODO: Implement All other IUnitOfWork methods
}
Your configuration will now look like this:
Func<IUnitOfWork> uowFactory =
() => new MyUnitOfWork(connectionString);
// Register the factory as Lazy<IUnitOfWork>
container.Register<Lazy<IUnitOfWork>>(
() => new Lazy<IUnitOfWork>(uowFactory),
Lifestyle.Scoped);
// Register the proxy that delays the creation of the UoW
container.Register<IUnitOfWork, DelayedUnitOfWorkProxy>(
Lifestyle.Scoped);
When a command or any other dependency needs an IUnitOfWork, they will get the DelayedUnitOfWorkProxy, and it is injected with a Lazy<IUnitOfWork>. So after the object graph is created, the unit of work itself will not be created yet. Only when one of the DelayedUnitOfWorkProxy method is called, such instance is created. The decorator will stay the same.
But even this might not be good enough. It is possible that your MVC controller (assuming you are building an ASP.NET MVC application) depends on a query that uses the unit of work, but the command handler does not. In that case you probably still wouldn't want to commit the unit of work, because the command handler (or one of its dependencies) still doesn't use the unit of work.
In that case what you’re actually trying to do is to isolate the execution of command handlers in their own scope. As if they are running in a different App Domain. You want them to be independent of the web request in which they execute.
In that case you need an hybrid lifestyle. With Simple Injector you can leave all your code and configuration in tact, but switch to an hybrid lifestyle like this:
container.Options.DefaultScopedLifestyle = Lifestyle.CreateHybrid(
() => container.GetCurrentLifetimeScope() != null,
new LifetimeScopeLifestyle(),
new WebRequestLifestyle());
Func<IUnitOfWork> uowFactory =
() => new MyUnitOfWork(connectionString);
// Register the factory as Lazy<IUnitOfWork>
container.Register<Lazy<IUnitOfWork>>(
() => new Lazy<IUnitOfWork>(uowFactory),
Lifestyle.Scoped);
// Register a proxy that depends on Lazy<IUnitOfWork>
container.Register<IUnitOfWork, DelayedUnitOfWorkProxy>(
Lifestyle.Scoped);
An hybrid lifestyle is a composite of two (or more) lifestyles and it contains a predicate delegate that the container will call to check which lifestyle should be applied.
With just this configuration nothing will happen, because the LifetimeScopeLifestyle requires you to explicitly start and stop a new scope. Without a scope the container.GetCurrentLifetimeScope() method will always return null, which means that the hybrid lifestyle will always pick the WebRequestLifestyle.
What you need is to start a new lifetime scope just before you resolve a new command handler. As always, this can be done by defining a decorator:
private sealed class LifetimeScopeCommandHandlerDecorator<T>
: ICommandHandler<T>
{
private readonly Container container;
private readonly Func<ICommandHandler<T>> decorateeFactory;
public LifetimeScopeCommandHandlerDecorator(Container container,
Func<ICommandHandler<T>> decorateeFactory)
{
this.decorateeFactory = decorateeFactory;
this.container = container;
}
public void Handle(T command)
{
using (this.container.BeginLifetimeScope())
{
var decoratee = this.decorateeFactory.Invoke();
decoratee.Handle(command);
}
}
}
You should register this decorator as last decorator (outer most decorator). Instead of depending on an ICommandHandler<T> this decorator depends on an Func<ICommandHandler<T>>. This makes sure that the decorated command handler will only get resolved when the Func<T> delegate is invoked. This postpones the creation and and allows the creation of a lifetime scope first.
Since this decorator depends on two singletons (both the container and the Func<T> are singletons), the decorator itself can also be registered as singleton. This is what your configuration might look like:
// Batch register all command handlers
container.Register(
typeof(ICommandHandler<>),
typeof(ICommandHandler<>).Assembly);
// Register one or more decorators
container.RegisterDecorator(
typeof(ICommandHandler<>),
typeof(TransactionCommandHandlerDecorator<>));
// The the lifetime scope decorator last (as singleton).
container.RegisterDecorator(
typeof(ICommandHandler<>),
typeof(LifetimeScopeCommandHandlerDecorator<>),
Lifestyle.Singleton);
This will effectively isolate the unit of work used by commands from any unit of work that is created outside the context of a command handler within the rest of the request.
There is a simple way to achieve what you are asking. There are overloaded versions of the RegisterDecorator extension method that accept a Predicate which, in combination with a marker interface, can be used to selectively apply a decorator.
Here's an example in code:
public interface ICommandHandler<T> where T : class { }
public interface IDontUseUnitOfWork { }
public class MyCommand { }
public class MyCommandHandler :
ICommandHandler<MyCommand>, IDontUseUnitOfWork { }
public sealed class UnitOfWorkCommandDecorator<T> :
ICommandHandler<T> where T : class
{
public UnitOfWorkCommandDecorator(ICommandHandler<T> decorated) { }
}
And the registration to apply the UnitOfWorkCommandDecorator to command handlers except those that are tagged with the IDontUseUnitOfWork interface:
container.RegisterDecorator(
typeof(ICommandHandler<>),
typeof(UnitOfWorkCommandDecorator<>),
x => !typeof(IDontUseUnitOfWork).IsAssignableFrom(x.ImplementationType));
This predicate feature is very useful and well worth getting to grips with.