I'm using Nancy with TinyIoC to solve the dependencies.
One dependency in particular needs to be application-lifecycle singleton.
If I do it with a default constructor it works:
container.Register<IFoo, Foo>().AsSingleton(); // WORKS
but if i try this with some arguments on the contructor it does not:
container.Register<IFoo>((c, e) => new Foo("value", c.Resolve<ILogger>())).AsSingleton();
// FAILS with error "Cannot convert current registration of Nancy.TinyIoc.TinyIoCContainer+DelegateFactory to singleton"
Whithout .AsSingleton(), it works again, but I don't get a singleton:
container.Register<IFoo>((c, e) => new Foo("value", c.Resolve<ILogger>()));
// Works, but Foo is not singleton
Any Ideas? I think the mistake should be obvious but I can't find it.
I've used up all my google-foo.
EDIT
The code runs here:
public class Bootstrapper : DefaultNancyBootstrapper
{
protected override void ConfigureApplicationContainer(TinyIoCContainer container)
{
base.ConfigureApplicationContainer(container);
// here
}
}
What you're doing there is telling TinyIOC "every time you want one of these, call my delegate", so if you want to use that method you have to handle the singleton aspect yourself.
Unless you particularly need the deferred creation it's easier to do:
container.Register<IFoo>(new Foo("value", c.Resolve<ILogger>()));
That will then always use that instance whenever you want an IFoo.
Related
I am using Azure Functions version 2.x. It has built-in support for dependency injection.
So I can register my service IMyService for DI at singleton scope using:
public class Startup : FunctionsStartup
{
public override void Configure(IFunctionsHostBuilder builder)
{
builder.Services.AddSingleton<IOther, DefaultOther>();
builder.Services.AddSingleton<IMyService, DefaultMyService>(); // IMyService depends on IOther.
}
}
An instance of DefaultMyService is created the first time the function gets executed. This means the first request is slower because it does heavy initialization that happens inside DefaultMyService (it populates cache, etc.).
Question: Is there a way to have DefaultMyService created earlier than the first request?
A similar question was asked for asp.net core, and the answers there suggests a few solutions, but none of them works in the context of a function app:
Option 1: Create an instance of my service (initialization happens here), and then register the instance (instead of registering the type)
var foo = new Foo();
services.AddSingleton<IFoo>(foo);
This doesn't work because in my case IMyService depends on other services, which are not instantiated at the time when I am registering IMyService in the Configure method. It fails with an error that's described here.
Option 2: Other suggestion is to use overloaded Configure method:
public void Configure(IApplicationBuilder app, IFoo foo)
{
...
}
This also doesn't work because in case of function app, the only configure method that gets executed is Configure(IFunctionsHostBuilder builder), and other overloads are not called.
because it does heavy initialization that happens inside DefaultMyService
This is where the core of the problem lies. As Mark Seemann explained here, Injection constructors should do nothing more checking for null and storing incoming dependencies. Any time you do any I/O or invoke the class's dependencies inside the constructor, you'll get in trouble.
Your question seems similar to this q/a, and my advise would be the same: extract the initialization logic out of the constructor and either do the following:
Do the initialization before wiring the object graph and supply the DI configuration with an initialized object, or
Resolve and invoke an object graph directly after the registration phase, and before the first request, in such way that the data can be initialized.
So basicly if i have a service MyMonkeyService which implements interface IMyMonkeyService and i make a register a DI object like :
SimpleIOC.Default.Register(Of IMyMonkeyService, MyMonkeyService)
How do i make sure that some developer after me not going to create new instance of MyMonkeyService somewhere in the application? I cant make Service's constructor private or protected, because then DI wouldnt work, if i create a Init() method on the service, it will still be available to the "new developer".
How about making MyMonkeyService a singleton?
You would have an implementation like this:
public class MyMonkeyService : IMyMonkeyService
{
private static MyMonkeyService _instance;
public static IMyMonkeyService Instance
{
get
{
// Gets the singleton if created, otherwise create a new instance
return _instance != null ? _instance : (_instance = new MyMonkeyService());
}
}
// Private constructor
private MyMonkeyService()
{
// ...
}
}
I don't know what DI framework you are using, but you would end up with something like the following:
SimpleIOC.Default.Register(Of IMyMonkeyService, MyMonkeyService.Instance);
Everytime your service is injected, the same instance will be used.
If you require multiple instances, you cant. Everything you make available to the DI container will be available for another developer.
You can write an analyzer though, which checks for instantiation of MyMonkeyService and emits an appropriate error.
This or this may help you getting started.
Roselyn Analyzers let you write code analysis tools that check the code for specific patterns and can emit errors and warnings accordingly. You can even define fixes for that pattern.
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.
Is it possible to register an interface in a registry, then "re-register" it to override the first registration?
I.E.:
For<ISomeInterface>().Use<SomeClass>();
For<ISomeInterface>().Use<SomeClassExtension>();
What I want here on runtime is that my object factory returns SomeClassExtension when I ask for ISomeInterface.
Thanks in advance!
Good news, I found out that yes. It all depends on the order that the registry rules are added to the object factory container. So if you are using multiple registry classes as I was doing, you need to find a way to give a priority to add them to the container.
In other words, instead of using the .LookForRegistries() which gets all the Registry classes in the wrong order, try to find all the Registry files, set them in the order you want and add them manually to the object factory container:
ObjectFactory.Container.Configure(x => x.AddRegistry(registry));
That way, you have full control on what rules you want.
Hope it helps :)
I just wanted to add my solution to the problem when I needed to override some parts of a registry in my SpecFlow test.
I did find this thread pretty early in my search, but it didnĀ“t really help me find the solution, so I hope it will help you.
My problem was that the "DataContext" in "StoreRegistry" (used by the application) use the "HybridHttpOrThreadLocalScoped" and I needed it to be "Transient" in my tests.
The code looked like this:
[Binding]
public class MySpecFlowContext
{
...
[BeforeFeature]
private static void InitializeObjectFactories()
{
ObjectFactory.Initialize(x =>
{
x.AddRegistry<StoreRegistry>();
x.AddRegistry<CommonRegistry>();
});
}
}
To override the scope setting you will need to explicitly set it in the registration.
And the override needs to be below what is overridden
The working code looks like this:
[Binding]
public class MySpecFlowContext
{
...
[BeforeFeature]
private static void InitializeObjectFactories()
{
ObjectFactory.Initialize(x =>
{
x.AddRegistry<StoreRegistry>();
x.AddRegistry<CommonRegistry>();
x.AddRegistry<RegistryOverrideForTest>();
});
}
class RegistryOverrideForTest : Registry
{
public RegistryOverrideForTest()
{
//NOTE: type of scope is needed when overriding the registered classes/interfaces, when leaving it empty the scope will be what was registered originally, f ex "HybridHttpOrThreadLocalScoped" in my case.
For<DataContext>()
.Transient()
.Use<DataContext>()
.Ctor<string>("connection").Is(ConnectionBuilder.GetConnectionString());
}
}
}
Went off on an interesting tangent today after reading this article on command handler decoration. I wanted to see if I could implement the pattern using Unity instead of SimpleInjector, and so far it is proving extremely difficult.
The first thing I had to do was install UnityAutoRegistration to resolve the open generic ICommandHandler<TCommand> interface. Current solution for that aspect is as follows:
Container = new UnityContainer().LoadConfiguration();
Container.ConfigureAutoRegistration()
.ExcludeSystemAssemblies()
.Include(type => type.ImplementsOpenGeneric(typeof(ICommandHandler<>)),
(t, c) => c.RegisterType(typeof(ICommandHandler<>), t)
)
.ApplyAutoRegistration()
;
This works for the first part, resolving any single ICommandHandler<TCommand>. What's proven frustrating so far is implementing a decoration handler. As soon as I add a second ICommandHandler<TCommand> as a decorator, Unity throws a StackOverflowException. I don't know enough about Unity internals, but I'm guessing this is because it can't figure out which instance to resolve to -- the command handler, or the command handler decorator -- since both implement the ICommandHandler<TCommand> interface.
Googling around led me first to this article, which explains how to do it in what I would consider a brute force method. I also found these related pages but none is a complete solution to my problem (and I am too ignorant to figure it out for myself).
I then found this article, which seems to address my same concerns. However beefy's solution does not account for dealing with open generics. Currently most of our dependencies are loaded from a unity section in the .config file, so I don't want to write a ton of compiled code for each handler or decorator. It seems like having some kind of UnityContainerExtension and DecoratorBuildStrategy is the right way to go, but I can't figure it out. I have been playing with beefy's code for a little while now, and am completely stuck. My attempts to modify his code to account for generics has led to BadImageFormatExceptions (An attempt was made to load a program with an incorrect format. (Exception from HRESULT: 0x8007000B)).
I like the idea of doing this to implement the decorator chaining, because it's short, and there is only 1 line per concern:
var container = new Container();
// Go look in all assemblies and register all implementations
// of ICommandHandler<T> by their closed interface:
container.RegisterManyForOpenGeneric(typeof(ICommandHandler<>),
AppDomain.CurrentDomain.GetAssemblies());
// Decorate each returned ICommandHandler<T> object with an
// TransactionCommandHandlerDecorator<T>.
container.RegisterDecorator(typeof(ICommandHandler<>),
typeof(TransactionCommandHandlerDecorator<>));
// Decorate each returned ICommandHandler<T> object with an
// DeadlockRetryCommandHandlerDecorator<T>.
container.RegisterDecorator(typeof(ICommandHandler<>),
typeof(DeadlockRetryCommandHandlerDecorator<>));
...but I don't want to change my container from Unity to Simple Injector if I don't have to.
SO my question is how could I go about implementing open generic decorator chaining using unity (plus UnityAutoRegistration)?
This would be the equivalent in Unity:
// Go look in all assemblies and register all implementa-
// tions of ICommandHandler<T> by their closed interface:
var container = new UnityContainer();
var handlerRegistrations =
from assembly in AppDomain.CurrentDomain.GetAssemblies()
from implementation in assembly.GetExportedTypes()
where !implementation.IsAbstract
where !implementation.ContainsGenericParameters
let services =
from iface in implementation.GetInterfaces()
where iface.IsGenericType
where iface.GetGenericTypeDefinition() ==
typeof(ICommandHandler<>)
select iface
from service in services
select new { service, implementation };
foreach (var registration in handlerRegistrations)
{
container.RegisterType(registration.service,
registration.implementation, "Inner1");
}
// Decorate each returned ICommandHandler<T> object with an
// TransactionCommandHandlerDecorator<T>.
container.RegisterType(typeof(ICommandHandler<>),
typeof(TransactionCommandHandlerDecorator<>),
"Inner2",
InjectionConstructor(new ResolvedParameter(
typeof(ICommandHandler<>), "Inner1")));
// Decorate each returned ICommandHandler<T> object with an
// DeadlockRetryCommandHandlerDecorator<T>.
container.RegisterType(typeof(ICommandHandler<>),
typeof(DeadlockRetryCommandHandlerDecorator<>),
InjectionConstructor(new ResolvedParameter(
typeof(ICommandHandler<>), "Inner2")));
I hope I understand the problem correctly and I was curious to try and get this to work and I'm by no means an expert on Unity but I was thinking of a solution that is a little easier to implement and would also be easier to do with a different container. It would seem like the only way to support the open generic as well as the other types is to have 2 separate containers (1 for the open generic) and one for your command handlers, this might not be the best way but it worked with Unity and I'm assuming will also be easier with others.
So I came up with this:
I created the containers as follows (you can use your convention approach still im sure for the handler container)
var container = new UnityContainer();
var container2 = new UnityContainer();
container2.RegisterType(typeof(ICommandHandler<QueryCommand>),
typeof(QueryCommandHandler));
container.RegisterInstance("Handlers", container2);
container.RegisterInstance(container);
container.RegisterType(typeof(ICommandHandler<>),
typeof(DecoratedHandler<>));
You see container 2 containing the Handlers as a named instance.
Then I just created a Generic base decorator class as per the requirement of the pattern:
public class DecoratorCommandHandler<TCommand>
: ICommandHandler<TCommand>
{
private ICommandHandler<TCommand> inner;
public DecoratorCommandHandler(
ICommandHandler<TCommand> inner)
{
this.inner = inner;
}
public virtual void Handle(TCommand command)
{
this.inner.Handle(command);
}
}
Second I created another Generic Handler that would wrap all the Decorations you want to do for your solution, here you will add decorating for TryCatch/Caching/Transactions or whatever else you want to apply to each command handler:
public class DecoratedHandler<TCommand>
: DecoratorCommandHandler<TCommand>
{
public DecoratedHandler(UnityContainer container)
: base(BuildInner(container))
{
}
private static ICommandHandler<TCommand> BuildInner(
UnityContainer container)
{
var handlerContainer =
container.Resolve<UnityContainer>("Handlers");
var commandHandler =
handlerContainer.Resolve<ICommandHandler<TCommand>>();
return new TryCatchCommandHandler<TCommand>(commandHandler);
}
}
You will notice that the first inner resolves the actual command handler as per the one you requested like QueryCommandHandler, UpdateCommandHandler, ExecuteCommandHandler or whatever one dealing with specifics. And then gets wrapped with all the decorators you want common to all of them.
Then I was able to resolve the correct handler, decorated in the correct way:
ICommandHandler<QueryCommand> handler =
container.Resolve<ICommandHandler<QueryCommand>>();
var cmd = new QueryCommand();
handler.Handle(cmd);
Hope this helps