Autofac, IDisposable and manually calling .Resolve in certain circumstances - c#

I've posted a general guideline question when it comes to IDisposable objects and using Autofac here: Dependency Injection and IDisposable. Unfortunately, I did not account for one particular scenario in our project and it's really a separate question that stands on its own, so will ask it here:
I have a Repository object that manages the life of a session object inside it. Thus, Repository object is IDisposable and destroys session (Repository is injected with a factory delegate at construction, instantiates session during first usage, and destroys session in IDisposable if session is not null). Per reference to StackOverflow question above, I understand that any object that is injected with my Repository object should not be implementing IDisposable since Autofac will handle disposing of my repositories, if it is injecting them.
Per mentioned StackOverflow thread, I've started cleaning up IDisposable usage from my objects until I stumbled upon NotificationPublisher class shown below. There are a few places like it where classes are injected with implementation of IComponentContext that acts as a factory. Resolution happens manually in a function, because the codebase does not know what handler needs to be injected until the runtime.
public class NotificationPublisher : INotificationPublisher
{
private readonly IComponentContext _container;
private readonly INotificationManager _notificationManager;
public NotificationPublisher(IComponentContext container,
INotificationManager notificationManager)
{
_container = container;
_notificationManager = notificationManager;
}
public IEnumerable<IAlertSubscription> Publish(Account account,
INotificationInitiator owner, INotificationEntity entity,
Int32 severity, CheckCycleContext monitoringContext)
{
var alertSubscriptions =
_notificationManager.GetAlertSubscriptions(account, owner, severity);
foreach (var alertSubscription in alertSubscriptions)
{
var destination = alertSubscription.GetConsumer();
Type handlerType = typeof (INotificationHandler<,>)
.MakeGenericType(entity.GetType(), destination.GetType());
using (var handler =
(INotificationCustomHandler)_container.ResolveOptional(handlerType))
{
if (handler == null) continue;
try
{
Retry.Execute(() => (handler).Send(entity, destination), 3, 500);
monitoringContext.Record(CheckCycleContext.CycleSeverity.Information,
string.Format("NotificationPublisher.Publish:{0}/{1}",
entity.GetType().Name, destination.GetType().Name), "Success");
}
catch (Exception ex)
{
monitoringContext.Record(CheckCycleContext.CycleSeverity.Error,
string.Format("NotificationPublisher.Publish:{0}/{1}",
entity.GetType().Name, destination.GetType().Name), ex.Message, ex,
new {entity, destination});
}
}
}
return alertSubscriptions;
}
}
I'm assuming that since INotificationCustomHandler is manually resolved, it must be manually disposed with the using statement, becuase implementations of INotificationCustomHandler are injected with implementations of IManager that is injected with implementations of IRepository.
Thus, in this situation I need to propagate IDisposable throughout my codebase which goes against what I was suggested in the prior SO question.
How do I manually resolve objects via factories when needed and yet let Autofac handle disposing?

When Autofac resolve a component that implements IDisposable this one will be linked with scope that has been configured when you registered it. When this scope will be disposed, all linked components will be disposed too. See http://autofac.readthedocs.org/en/latest/lifetime/disposal.html for more information.
In your case, if INotificationCustomHandler is registered as InstancePerDependency (default) or InstancePerLifetimeScope, INotificationCustomHandler resolved by _container, will be disposed when _container will be disposed too.
If this is what you want, you don't have to call .Dispose on these components.
If you want to manually control the lifetime of your objects, you can create your own lifetime scope.
using(ILifetimeScope scope = this._container.BeginLifetimeScope())
{
var handler = (INotificationCustomHandler)scope.ResolveOptional(handlerType);
if(handler != null)
{
Retry.Execute(() => handler.Send(entity, destination));
}
} // handler will be disposed here if needed
you should also have a look to owned instance which acts like a mini factory.
if(!container.ComponentRegistry.IsRegistered(new TypedService(handlerType)))
{
continue;
}
Type handlerFactoryType = typeof(Func<>).MakeGenericType(
typeof(Owned<>).MakeGenericType(handlerType));
var handlerFactory = (Func<Owned<INotificationCustomHandler>>)container
.Resolve(handlerFactoryType);
using(Owned<INotificationCustomHandler> ownedHandler = handlerFactory())
{
INotificationCustomHandler handler = ownedHandler.Value;
Retry.Execute(() => handler.Send(entity, destination), 3, 500);
} // handler will be disposed here

Related

Autofac: creating nested scopes per instance on-the-fly

I would like to implement an application-wide container and a (nested) one for each project created by the user. I looked into Owned<T>, but then - as far as I could figure it out - my internal collection of projects would have to be <Owned<Project>> which I do not want and also I failed to inject a project dependency into objects used within the project scope ("circular component dependency"). I considered using a new ContainerBuilder within the project factory, but then the "nested" aspect is missing.
A few exapmles of classes (with the dependencies) I would like to have:
In a global scope: ProjectManager(IProjectFactory)
In each project's scope: Project(IDocumentFactory documentFactory), Document(IProject project, IProjectSettings settings).
So for the project's scope I would register IDocumentFactory, IProjectSettings (and the project itself?).
When a project is closed/disposed all created dependencies should, of course, also be disposed.
If possible, the concrete classes (except for the ProjectFactory) should be Autofac-agnostic.
FYI: The application is a desktop application using C# and Autofac 4.8.
Thanks!
UPDATE: Thanks for your comments, the discussion helped me find my own opinion. Currently I'm settling for something like this in my ProjectFactory:
public Project Create()
{
var scope = _globalScope.BeginLifetimeScope(MyIocHelper.RegisterProjectDependencies);
var p = scope.Resolve<Project>();
_projectScopes.Add(p, scope);
p.Disposing += project_Disposing;
return p;
}
Things to note:
As far as I can tell, using a tag for the lifetime scope is not necessary.
Project raises a Disposing event when its Dispose method is called the first time.
The factory keeps a Dictionary<Project, ILifetimeScope> and cleans it up when the project is disposed.
You can accomplish what you are looking for with a combination of named lifetime scopes and instance-per-lifetime-scope registrations.
Documentation here: http://autofac.readthedocs.io/en/latest/lifetime/working-with-scopes.html#tagging-a-lifetime-scope
You need to:
register your ProjectManager as SingleInstance
register Project as this:
builder.Register<Project>()
.As<IProject>()
.InstancePerMatchingLifetimeScope("project");
This will guarantee that a Project can be resolved (e.g. by a Document) once per each scope tagged as "project".
Implement an OpenProject (or something along) method in ProjectManager. This method should instantiate a LifetimeScope tagged as "project", register in it the IDocumentFactory, IProjectSettings, so they are resolved only once for each project scope, and attach the scope itself onto the Project instance. This is crucial: you need the scope to be disposed when you dispose the project.
public class ProjectManager : IProjectFactory
{
private readonly ILifetimeScope _scope;
public ProjectManager(ILifetimeScope scope)
{
// this is going to be the global scope.
_scope = scope;
}
public Project OpenProject(IDocumentFactory docFactory, IProjectSettings settings)
{
var projectScope = _scope.BeginLifetimeScope("project");
projectScope.RegisterInstance(docFactory).AsImplementedInterfaces();
projectScope.RegisterInstance(settings).AsImplementedInterfaces();
return projectScope.Resolve<Project>();
}
}
public class ProjectScope : IDisposable
{
private readonly ILifetimeScope _scope;
public ProjectManager(ILifetimeScope scope)
{
// this is going to be the project scope.
_scope = scope;
}
public void Dispose() {
if (_scope != null) {
_scope.Dispose();
_scope = null;
}
}
}
public class Project : IDisposable
{
private readonly ProjectScope _scope;
public Project(ProjectScope scope /*, ...*/)
{
_scope = scope;
}
public void Dispose() {
// pay attention that this method will be called 2 times, once by you
// and another time by the underlying LifetimeScope. So this code should
// handle that gracefully (so the _scope == null).
if (_scope != null) {
_scope.Dispose();
_scope = null;
}
}
}
Given all this, you keep every using Autofac out of every class, with the 2 exceptions of the global manager and the ProjectScope. You can change some bits on how the scope is handled, if you accept a single using Autofac in the Project class itself: you can get directly the ILifetimeScope and dispose of it directly.
Hope this helps!

Proper way to override dependencies within a scope

I'm using Simple Injector. I have a background processor which is using DI from the start. It will pickup jobs to run, and run them. However, each job needs to run within its own scope so that I can override some contextual dependencies. For example, the job needs to run within a specific security context (the one from which it was created), so I need to start a new scope and override the ISecurityContext injection so the job will be properly secured.
To accomplish this, I was creating a new container (with the proper ISecurityContext) and starting a scope, then running the job, but I'm not sure if this is an appropriate thing to do.
RunJob
private readonly Func<ISecurityContext, Container> _containerFactory;
internal async Task RunJob(BackgroundJob job) {
var parameters = job.GetParameters();
var securityContext = parameters.SecurityContext;
using (var container = _containerFactory(securityContext))
using (AsyncScopedLifestyle.BeginScope(container)) {
// Run the job within this scope.
}
}
DI Bits
container.RegisterSingleton<Func<ISecurityContext, Container>>(() => securityContext => {
var c = new Container();
RegisterDependencies(c);
c.Options.AllowOverridingRegistrations = true;
c.Register<ISecurityContext>(() => securityContext, Lifestyle.Scoped);
return c;
});
It doesn't feel right to me, but I'm not sure what the correct solution is.
The Simple Injector documentation warns about what you are doing by stating:
Warning: Do not create an infinite number of Container instances (such as one instance per request). Doing so will drain the performance of your application. The library is optimized for using a very limited number of Container instances. Creating and initializing Container instances has a large overhead, but resolving from the Container is extremely fast once initialized.
In general, you should create only one Container instance per application. This not only holds from a performance perspective, but the creation of this sort of 'child containers' in general is littered with quirks and flaws. For instance, how to ensure that registrations are singletons across the application?
So instead, don't abuse the container for your runtime state, but store it elsewhere. You can use a Scope instance as dictionary for scoped state, but it's as easy to create a simple wrapper for ISecurityContext that is registered as Scoped instance and gets initialized directly after the scope is created as seen in the following example.
// Can be part of your Composition Root
internal sealed class SecurityContextWrapper : ISecurityContext
{
// One of the rare cases that Property Injection makes sense.
public ISecurityContext WrappedSecurityContext { get; set; }
// Implement ISecurityContext methods here that delegate to WrappedSecurityContext.
}
// Composition Root. Only have 1 container for the complete application
c = new Container();
RegisterDependencies(c);
c.Register<SecurityContextWrapper>(Lifestyle.Scoped);
c.Register<ISecurityContext, SecurityContextWrapper>(Lifestyle.Scoped);
// Job logic
private readonly Container _container;
internal async Task RunJob(BackgroundJob job) {
var parameters = job.GetParameters();
var securityContext = parameters.SecurityContext;
using (AsyncScopedLifestyle.BeginScope(_container)) {
// Resolve the wapper inside the scope
var wrapper = _container.GetInstance<SecurityContextWrapper>();
// Set it's wrapped value.
wrapper.WrappedSecurityContext = securityContext;
// Run the job within this scope.
}
}
Alternatively, if you use Scope as state, you can inject a Scope instance as constructor argument of SecurityContextWrapper. That removes the need to use Property Injection, but does make your SecurityContextWrapper dependent on Simple Injector:
// Can be part of your Composition Root
internal sealed class SecurityContextWrapper : ISecurityContext
{
ISecurityContext _wrappedSecurityContext;
public SecurityContextWrapper(Scope scope)
{
_wrappedSecurityContext= (ISecurityContext)scope.GetItem(typeof(ISecurityContext));
}
// Implement ISecurityContext methods here that delegate to WrappedSecurityContext.
}
// Composition Root. Only have 1 container for the complete application
c = new Container();
RegisterDependencies(c);
c.Register<ISecurityContext, SecurityContextWrapper>(Lifestyle.Scoped);
// Job logic
private readonly Container _container;
internal async Task RunJob(BackgroundJob job) {
var parameters = job.GetParameters();
var securityContext = parameters.SecurityContext;
using (var scope = AsyncScopedLifestyle.BeginScope(_container)) {
// Set it's wrapped value.
scope.SetItem(typeof(ISecurityContext), securityContext);
// Run the job within this scope.
}
}

Castle windsor proxy generate memory leak

Castle windsor is used in MVC application as it is described here:
Plugging Windsor in MVC
In my application there is one difference and that is method AddControllerLoggingFunctionality:
var controller = ((IController)container.Kernel.Resolve(controllerType)).AddControllerLoggingFunctionality();
This method is in logger class:
[DebuggerStepThrough]
public static class Logger
{
private static readonly Castle.DynamicProxy.ProxyGenerator proxyGenerator;
static Logger()
{
proxyGenerator = new Castle.DynamicProxy.ProxyGenerator();
Castle.DynamicProxy.Generators.AttributesToAvoidReplicating.Add(
typeof(ServiceContractAttribute));
}
public static TInterface AddControllerLoggingFunctionality<TInterface>(this TInterface implementation)
where TInterface : class
{
if (implementation == null)
{
throw new ArgumentNullException("implementation");
}
if (!typeof(TInterface).IsInterface)
{
throw new Exception("Type of 'TInterface' must be interface.");
}
Castle.DynamicProxy.ProxyGenerationOptions options =
new Castle.DynamicProxy.ProxyGenerationOptions();
var origAttribs = implementation.GetType().GetCustomAttributesData();
if (origAttribs != null)
{
foreach (var origAttrib in origAttribs)
{
options.AdditionalAttributes.Add(
AttributeUtil.CreateBuilder(origAttrib));
}
}
return (TInterface)proxyGenerator.CreateInterfaceProxyWithTarget<TInterface>(
implementation,
options,
new ControllerLoggingInterceptor(implementation.GetType()));
}
}
And
Can someone explain this? Why IController can call AddControllerLoggingFunctionality and what does it?
Because of this change, this controllers are never released from memory(when
container.Kernel.ReleaseComponent(controller); is called) and I get memory leak.
The "Object tracked by release policy" counter increase all the time.
If i remove AddControllerLoggingFunctionality, then "Object tracked by release policy" counter decrease each time when I call ReleaseComponent and memory leak doesn't happen.
You aren't call Release() on the controller but are calling it on the proxy you manually created so Release() is just a no-op to Windsor as it doesn't know about that object and so keeps tracking the controller component.
If you use Windsor's built-in interception support you don't have to worry about this problem as Windsor will know how to dispose of the component when passed its own internally managed proxy.
If you want to test this before changing to Windsor's built-in support, cast your proxy to Castle.DynamicProxy.IProxyTargetAccessor and call DynProxyGetTarget() to get your controller instance which you'll need to pass to Release().
(This answer is copied from our discussion on the Castle Users mailing list)

How does autofac determine lifetime scope on injected parameters

I have been having a nasty Memory Leak issue while using Autofac, which I think I may have resolved. But, I am curious about if the service StatsService injected in the StatsRefreshMessageHandler class is using the lifetime scope of the Helpers class which called it.
Register Service
builder.RegisterType<StatsService>().InstancePerLifetimeScope();
My helpers class is injected with a lifetime scope, it then calls the appropriate message handler. In this example it will be the StatsRefreshMessageHandler
public class Helpers
{
private ILifetimeScope _lifetimeScope;
private ILifetimeScope _lifetimeScope;
public Helpers(ILifetimeScope lifetimeScope)
{
_lifetimeScope = lifetimeScope;
}
public void ProcessMessage<T>(T message) where T : class
{
//Voodoo to construct the right message handler type
Type handlerType = typeof(IMessageHandler<>);
Type[] typeArgs = { message.GetType() };
Type constructed = handlerType.MakeGenericType(typeArgs);
//Handle the message
using (var messageScope = _lifetimeScope.BeginLifetimeScope())
{
var handler = messageScope.Resolve(constructed);
var methodInfo = constructed.GetMethod("Handle");
//this is where it call the message handler
methodInfo.Invoke(handler, new[] { message });
}
}
}
And the class (StatsRefreshMessageHandler) below uses standard IOC Injection... But, the question here is where is StatsService resolving from? I assume it is from the lifetime scope of the caller (Helpers), but if it is resolving from the root Kernel, then I still am going to have problems.
public class StatsRefreshMessageHandler : IMessageHandler<StatsRefreshMessage>
{
private readonly StatsService _statsService;
public StatsRefreshMessageHandler(StatsService statsService)
{
_statsService = statsService;
}
public void Handle(StatsRefreshMessage message)
{
_statsService.UpdateStatsCache(DateTime.UtcNow);
Console.WriteLine("DONE STATS");
}
}
There is some detailed documentation about how lifetime scope is determined for objects on the Autofac site. That can probably help clear up some of the questions you may have.
Some quick answers:
The handler you resolve from the messageScope will go in the lifetime scope for which it was registered:
SingleInstance registration will come from the container so it can be shared later with other resolve calls.
InstancePerLifetimeScope and InstancePerDependency will come from the messageScope and will be disposed when `messageScope is disposed.
The StatsService in the constructor of StatsRefreshMessageHandler will also come from messageScope because that's where the handler (the consumer) is being resolved. It will also obey the lifetime scope registration as noted above (e.g., if StatsService is SingleInstance it will end up in the container).

Autofac - Components ignore dependency defined in lifetime scope

I could well be misunderstanding something here, so perhaps there is a simple answer here but I'm currently scratching my head.
I have a class UnitOfWork that implements IUnitOfWork (yes yes I know). The constructor for unit of work takes an IPrincipalFactory. TResponder is the top level of the graph which takes an IUnitOfWork.
I'm trying to register the ApplicationPrincipalFactory as a specific instance in a lifetime scope... it's dependant on some properties passed to the HandleAsync function. I'm doing the following:
public async Task<TResponse> HandleAsync<TMessage, TResponse, TResponder>(TMessage message)
where TMessage : class
where TResponder : IRespondAsync<TMessage, TResponse>
{
using (var scope = this.BeginLifetimeScope(message))
{
var responder = scope.Resolve<TResponder>();
return await responder.Respond(message);
}
}
private ILifetimeScope BeginLifetimeScope<TMessage>(TMessage message)
{
var unwrapped = GetDomainContext(message);
var applicationPrincipalFactory = this.CreateApplicationPrincipalFactory(unwrapped);
var lifetime = this.container.BeginLifetimeScope(
r => r.RegisterInstance(applicationPrincipalFactory).As<IPrincipalFactory>());
return lifetime;
}
private ApplicationPrincipalFactory CreateApplicationPrincipalFactory(IDomainContext unwrapped)
{
var applicationPrincipalFactory =
new ApplicationPrincipalFactory(
unwrapped.Tenant,
unwrapped.ActingTenant,
unwrapped.Username);
return applicationPrincipalFactory;
}
Based on everything I've read, defining the dependency within BeginLifetimeScope(r => should override the parent container binding, so when I call resolve, it should all slot neatly together.
However, I get an exception:
None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'Platform.Engine.Persistence.UnitOfWork' can be invoked with the available services and parameters: Cannot resolve parameter 'Platform.Engine.Security.IPrincipalFactory principalFactory' of constructor
I am not registering the IPrincipalFactory anywhere other than in this method. The IUnitOfWork is defined in the outer scope as follows:
builder.RegisterType<UnitOfWork>().As<IUnitOfWork>().InstancePerLifetimeScope();
I have also tried re-defining the unitofwork registration within the child container in case it was an issue cause by registering it in the outer container rather than the lifetime one:
var lifetime = this.container.BeginLifetimeScope(
r => r.RegisterInstance(applicationPrincipalFactory).As<IPrincipalFactory>());
var overrides = new ContainerBuilder();
overrides.RegisterType<UnitOfWork>().As<IUnitOfWork>();
overrides.Update(lifetime.ComponentRegistry);
return lifetime;
I'm not sure what I'm missing... any ideas or suggestions?
Register your factory with the rest of your types during the initial container configuration.
builder.RegisterType<ApplicationPrincipalFactory>().As<IPrincipalFactory>();
Then in your lifetime scope resolve a delegate factory that you can pass the context into.
var factory = container.Resolve<Func<IDomainContext, IPrincipalFactory>>();
var instance = factory(context);
You could also add three string parameters to the Func<> signature, but since you already have a nice context object I would just pass that in instead.
Finally, use the factory as needed.
instance.DoesSomethingButNotSureWhat();
That will prevent you from having to update the lifetime scope just to pass in the context parameter.

Categories