Simple Injector gives lifestyle mismatch error while both classes are registered as singleton - inversion-of-control

So I have this Simple Injector IoC wire up code
container.RegisterSingleton<IMsgProcessor, PrometheusTickerPublisher>();
container.RegisterSingleton<ICollector, UpdatesPerSecondDataCollector>();
And when I try and run my app I am getting this error message
A lifestyle mismatch is encountered. PrometheusTickerPublisher
(Singleton) depends on UpdatesPerSecondDataCollector (Transient).
Lifestyle mismatches can cause concurrency bugs in your application.
Please see https://simpleinjector.org/dialm to understand this problem
and how to solve it.
I don't get this at all. Both items are registered as singletons. I then changed the registration to this, to see if I could be more explicit about it being a singleton
container.RegisterSingleton<IMsgProcessor, PrometheusTickerPublisher>();
container.AddRegistration(typeof(ICollector), CreateCollectorRegistration(container));
internal static Registration CreateCollectorRegistration(Container container)
{
return
Lifestyle.Singleton.CreateRegistration<ICollector>(
() =>
{
var timeProvider = container.GetInstance<ITimeProvider>();
return new UpdatesPerSecondDataCollector(timeProvider);
}, container);
}
But this gives the same error
At this point I am completely lost, Any ideas

Calling Container.Verify() at the end of the registration process will check the container's health. If you do that, it would give you even more feedback:
The configuration is invalid. The following diagnostic warnings were reported:
-[Lifestyle Mismatch] PrometheusTickerPublisher (Singleton) depends on UpdatesPerSecondDataCollector (Transient).
-[Short Circuited Dependency] PrometheusTickerPublisher might incorrectly depend on unregistered type UpdatesPerSecondDataCollector (Transient) instead of ICollector (Singleton).
-[Ambiguous Lifestyles] The registration for UpdatesPerSecondDataCollector (Transient) maps to the same implementation (UpdatesPerSecondDataCollector) as the registration for ICollector (Singleton) does, but the registration maps to a different lifestyle. This will cause each registration to resolve to a different instance.
-[Ambiguous Lifestyles] The registration for ICollector (Singleton) maps to the same implementation (UpdatesPerSecondDataCollector) as the registration for UpdatesPerSecondDataCollector (Transient) does, but the registration maps to a different lifestyle. This will cause each registration to resolve to a different 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 most interesting part here is the Short Circuited Dependency warning:
-[Short Circuited Dependency] PrometheusTickerPublisher might incorrectly depend on unregistered type UpdatesPerSecondDataCollector (Transient) instead of ICollector (Singleton).
In other words, Simple Injector detects that you registered UpdatesPerSecondDataCollector through its ICollector as Singleton, but you are circumventing that ICollector registration by depending directly on the UpdatesPerSecondDataCollector implementation instead. This is called short-circuited, because instead of using the ICollector registration, you go directly to the (unregistered) implementation. This might cause all sorts of problems.
Because there is no explicit registration for UpdatesPerSecondDataCollector, Simple Injector will implicitly register it for you, and it uses the Transient lifestyle (unless you specify otherwise). The registration for ICollector, however, is a Singleton, so that will likely cause problems. This is again noted in the Ambiguous Lifestyles warning:
-[Ambiguous Lifestyles] The registration for UpdatesPerSecondDataCollector (Transient) maps to the same implementation (UpdatesPerSecondDataCollector) as the registration for ICollector (Singleton) does, but the registration maps to a different lifestyle. This will cause each registration to resolve to a different instance.
Without calling Verify, all these issues stay undetected. The only verification Simple Injector does when resolving a type is the Lifestyle Mismatch, which is why you only got the following error:
A lifestyle mismatch is encountered. PrometheusTickerPublisher (Singleton) depends on UpdatesPerSecondDataCollector (Transient).
Long story short, you didn't register UpdatesPerSecondDataCollector by itself, but only by its ICollector abstraction, causing Simple injector to implicitly make a Transient registration for UpdatesPerSecondDataCollector on your behalf. Because this registration is Transient, Simple Injector blocked the injection of it into the Singleton class PrometheusTickerPublisher. If you would have called Container.Verify(), there would be a very detailed problem description of what is going wrong, which is much more than just a simple Lifestyle Mismatch.

Ok so I found out what the issue was, my class was expecting the exact UpdatesPerSecondDataCollector type rather than an ICollector, so I guess since I was not registering the type explicitly it was being resolved as transient each time by SimpleInjector. Solution was just to do this in IOC registration instead
container.RegisterSingleton<UpdatesPerSecondDataCollector>();
That is what my downstream class was expecting
Case closed

Related

How inject dependency in custom TelemetryInitializer?

We are using Autofac 4 for DI and I started experimenting with AI a short while ago. Now I created a IdentityTelemetryInitializer class which needs and IIdentityProvider to be able to get the ID of the current authorized user and set it add it to the context. I cannot find a way in which to inject dependencies into a TelemetryInitializer. If I define a contructor that takes an IIdentityProvider, the custom initializer is skipped altogether.
Any ideas are welcome. I was thinking of having the user ID also set as the Thread Principal so that we can access it this way, but I was hoping I could use DI for this?
You cannot inject dependencies using a constructor as the initializer initialized internally using the default (empty) constructor. When you explicitly defined a new ctor you've actually 'removed' the default one, thus the initializer was skipped altogether, as you've mentioned.
Therefore, the only way is to resolve the dependencies during the 'Initialize' method, after registering them on application startup.
ctx.RegisterType<MyService>().As<IService>().AsSelf(); // on application startup
ctx.Resolve<IService>(); // during initializer 'Initialize' method
You might look at the question I asked here
How to have "Request" events with authenticated user id ?
because I had managed to have the TelemetryInitializer working, passing user id via the HttpContext as suggested by #yonisha.
Off course it's not as lean as what you try to achieve.
The Telemetry Initializer is called each time you instanciate a Telemetry class, so really depending of how you manage them. Btw I am looking for good advice/best pratice on that : for the moment I have one private instance on each Controller that need to track something, but that does not smell good due to lifetime of Controller.

ServiceFabric StatefulService method passed Actor Proxy DataContract error

I have a StatefulService with a method. The first argument of the method accepts an interface type that corresponds to one of my Actors. The Actor calls the service method using ServiceProxy, passing this in as the first argument. This compiles file. The signatures match.
When running however, I get an error about an unexpected type of IMyActorType not being known to the DataContractSerializer. I know what this message means. Does ServiceProxy not handle ActorReferences? I know ActorProxy works. I can pass one Actor to another Actor using ActorProxy.
Or is this maybe some problem in my configuration of the StatefulService? Something with my ServiceReplicaListener setup?
I have worked around this issue for now by changing the method signatures of my StatefulService methods to ActorReference. That serializes fine, and I can unpack it on the other side. I would much rather have the proper typing, however.
Service Proxy does not handle the Actor references like Actor Proxy does. Services stack is independent of the actor and does not have knowledge of the actor references. Instead of passing the actor interface, you can pass the actor reference (https://msdn.microsoft.com/en-us/library/azure/microsoft.servicefabric.actors.actorreference.get.aspx) and then bind (https://msdn.microsoft.com/en-us/library/azure/microsoft.servicefabric.actors.actorreference.bind.aspx) the actor reference to the actor interface type on the receiving side. You can cast the output of the binding method to the actor interface.
You need to pass a simple DataContract-decorated POCO and not an interface. DataContractSerializer won't work on an interface. The same rules that would apply for WCF also apply to Service Fabric.

What does kernel.Bind<SomeType>().ToSelf() do?

I understand the following Ninject registration:
kernel.Bind<ISomeType>().To<SomeTypeImplementation>();
which tells Ninect to fulfill requests for ISomeType by using SomeTypeImplementation.
However I'm not sure what the following is good for.
kernel.Bind<ApplicationDbContext>().ToSelf();
Which was suggested that I use from this question:
What ninject binding should I use?
It makes ApplicationDbContext "self-bindable". If you don't have an interface to bind to, you can bind to the class itself. It's more useful if you add a scope to the call such as:
kernel.Bind<ApplicationDbContext>().ToSelf().InRequestScope();
Any time it sees the ApplicationDbContext that needs to be injected, it will reuse the same object as long as it is in the same HTTP request.
The default scope is transient, which means that any time a class requests ApplicationDbContext it will create a new instance of it. This can be problematic if you have two classes that both need to use the context in the same transaction. That is why you will often see it done with InRequestScope().
By self-binding a type, you enable that type for the following:
Lifecycle Management by the container.
Enable the container to inject dependencies into other types that depend on the self-bound type, and inject dependencies of this type into its instances likewise.
Very useful if you just have one single implementation or you don't need to use abstractions for some reason.

Sharprepository Autofac InstancePerApiRequest in Webapi environment not working

Does anyone have a working example of sharprepository intergration with autofac using InstancePerApiRequest for DbContext?
I am registering my dbcontext thusly:
builder.RegisterType<AuditTestEntities>().As<DbContext>().InstancePerApiRequest();
If I remove the InstancePerApiRequest, sharprepository is able to get a dbcontext. But with the InstancePerApiRequest, I get the error message pasted below. Basically the crux of the error is, I suspect, the way sharprepository makes the call:
No scope with a Tag matching 'AutofacWebRequest' is visible from the scope in which the instance was requested. This generally indicates that a component registered as per-HTTP request is being requested by a SingleInstance() component (or a similar scenario.) Under the web integration always request dependencies from the DependencyResolver.Current or ILifetimeScopeProvider.RequestLifetime, never from the container itself.
The full error stack:
iisexpress.exe Error: 0 : Operation=DefaultHttpControllerActivator.Create, Exception=System.InvalidOperationException: An error occurred when trying to create a controller of type 'AccountController'. Make sure that the controller has a parameterless public constructor. ---> Autofac.Core.DependencyResolutionException: An exception was thrown while invoking the constructor 'Void .ctor()' on type 'AccountRepository'. ---> Could not resolve type 'System.Data.Entity.DbContext' using the 'AutofacDependencyResolver'. Make sure you have configured your Ioc container for this type. View the InnerException for more details. (See inner exception for details.) ---> SharpRepository.Repository.Ioc.RepositoryDependencyResolverException: Could not resolve type 'System.Data.Entity.DbContext' using the 'AutofacDependencyResolver'. Make sure you have configured your Ioc container for this type. View the InnerException for more details. ---> Autofac.Core.DependencyResolutionException: No scope with a Tag matching 'AutofacWebRequest' is visible from the scope in which the instance was requested. This generally indicates that a component registered as per-HTTP request is being requested by a SingleInstance() component (or a similar scenario.) Under the web integration always request dependencies from the DependencyResolver.Current or ILifetimeScopeProvider.RequestLifetime, never from the container itself.
Okay found the issue. There is a problem with using the SharpRepository AutofacDependencyResolver when using the MVC or Web API integration and trying to use the scope InstancePerApiRequest or InstancePerHttpRequest. Autofac expects those items to be resolved from the System.Web.DependencyResolver.Current instead of from the Autofac IContainer directly as the AutofacDependencyResolver is currently doing.
Here is how you can fix the issue right now until we make an overload for AutofacDependencyResolver that fixes the issue.
You will need to create your own dependency resolver within your project like this one:
public class CustomAutofacDependencyResolver : BaseRepositoryDependencyResolver
{
private readonly IDependencyResolver _resolver;
public CustomAutofacDependencyResolver(IDependencyResolver resolver)
{
_resolver = resolver;
}
protected override T ResolveInstance<T>()
{
return _resolver.GetService<T>();
}
protected override object ResolveInstance(Type type)
{
return _resolver.GetService(type);
}
}
And then register it with SharpRepository so it will use it to resolve the DbContext and then it will work as expected.
RepositoryDependencyResolver.SetDependencyResolver(new CustomAutofacDependencyResolver(DependencyResolver.Current));
** Update**
I was testing with MVC and able to replicate the error and fix it but that doesn't work with Web API. I am used to using StructureMap where it works fine using the GlobalConfiguration.Configuration.DependencyResolver.
It seems the issue is that Autofac needs a IDependencyScope that you can access from the HttpRequestMessage but I'm not seeing a way to get to that outside of the ApiController. This describes the issue and the reason: https://groups.google.com/forum/#!msg/autofac/b3HCmNE_S2M/oMmwFE5uD80J
Unfortunately right now I'm at a bit of a loss on the best way to handle this. But I'll keep thinking about it.
So, I was able to get mine working by changing the lifetime scope to InstancePerLifetimeScope. I don't know whether this has any unforeseen consequences or not. Everything appears to be working fine for me so far.

Autofac Session Scope

I am investigating the use of Autofac in our web application having previously used Castle Windsor in the past.
The thing that I really like with Autofac is being able to express dynamic component construction through lamda expressions, as opposed to creating DependancyResolvers etc. in Windsor.
One scenario I have is that I want a particular component to be registered at ASP.NET session level scope. With Windsor I would create/source a new LifestyleManager, however with Autofac I came up with this:
//Register SessionContext at HTTP Session Level
builder.Register(c =>
{
HttpContext current = HttpContext.Current;
//HttpContext handes delivering the correct session
Pelagon.Violet.Core.Interfaces.SessionContext instance = current.Session["SessionContext"] as Pelagon.Violet.Core.Interfaces.SessionContext;
if (instance == null)
{
instance = c.Resolve<Pelagon.Violet.Core.Interfaces.SessionContext>();
current.Session["SessionContext"] = instance;
}
return instance;
})
.FactoryScoped();
Which at some point I might be able to turn into an extension method. I accept this implemtation will bomb if the HttpContext.Current.Session is null as it should only be used in a web app.
The question is:
What is the best practice for such a registration in Autofac. I have seen a lot of mention about the use of nested containers etc. but no concrete examples, and I am keen to understand what might be wrong with the above approach (only thing I can think of is the automatic disposal stuff).
Thanks.
This looks fine.
Marking the component 'ExternallyOwned()' will ensure that Autofac doesn't call Dispose() on it.
The only gotchas here are that your session-scoped component could resolve dependencies of its own via the current container, and thus hold references to things that may belong to the current request (for instance.) This should be easy to spot in testing though.