I'm trying to use autofac DI in my application. I created a wrapper class to abstract away all the autofac dlls:
FrameworkDependencyResolver : Logger, IFrameworkDependencyResolver
In this class I hold the container builder, and register all my dependencies in the application root. After registering my types I build it and hold the container:
Icontainer _container;
ContainerBuilder _builder
public FrameworkDependencyResolver()
{
_builder = new ContainerBuilder();
}
Deep in my application i want to use the FrameworkDependencyResolver object to resolve protocols and open connections to external applications, therefore I registered this object as IFrameworkDependencyResolver with the following code:
_builder.RegisterInstance(obj).As<T>();
Obj is thr FrameworkDependencyResolver, T is the interface
In my starter thread, I resolve object that takes the FrameworkDependencyResolver in his ctor, and it works perfectly, resolvings are fine, however when I resolve an inner layer(on new thread) that takes the FrameworkDependencyResolver in it's ctor and try to resolve a registered protocol object I face deadlock.
Exmaple:
main:
var rootResolver = new FrameworkDependencyResolver();
rootResolver.RegisterType<IClass3, Class3>(Lifecycles.Singleton);
rootResolver.RegisterType<IClass2, Class2>(Lifecycles.Singleton);
rootResolver.RegisterType<Container, TestContainer>(Lifecycles.Singleton);
rootResolver.RegisterObject<IFrameworkDependencyResolver, FrameworkDependencyResolver>(rootResolver);
rootResolver.BuildContainer();
rootResolver.Resolve<TestContainer>();
Console.ReadKey();
TestContainer code:
public TestContainer(IFrameworkDependencyResolver resolver) : base(resolver){}
protected override void InitializeContainer()
{
_class2 = DependencyResolver.Resolve<IClass2>();
Thread.Sleep(20000);
Console.WriteLine("Container initialize finished");
}
Class2 code:
public class2(IFrameworkDependencyResolver resolver)
{
_resolver = resolver;
var thread = new Thread(startMethod);
thread.Start();
Console.WriteLine("Class2 ctor ended");
}
void StartMethod()
{
_class3 = _resolver.Resolve<IClass3>();
Console.WriteLine("Start method finished");
}
The output of this simple example program is:
Class2 ctor ended
Container initialize ended
Start method finished
Meaning that the thread I created is waiting for the main thread to finish and only than it can resolve. I want to prevent this and make it possible to resolve anytime from every thread. Please help me understand what is causing this.
Thank you
Edit:
The problem is not solved because autofac resolves singletons from the root scope..I believe my problem is similar to the one described here : Autofac resolving a singleton creates a bottleneck
but I don't really understand the solution
Edit 2:
for the bottleneck issue I learned that ctors should not contain logic at all.
I also learned I probably shouldn't pass around my IFrameworkDependencyResolver object and should probably use Func<>.
My application structure:
I have a layer in my application that handles connection requests and for every kind of request creates a different kind of protocol (a different protocol object)
// For example lets say a protocol takes in ctor these 3 services + runtime configuration object:
public Protocol1(IFramingAgent, IFramingAlgorithm, IFramingParser, configObject configuration)
Each service is registered with key because each protocol uses a different one
And here is my terrible class:
public class ProtocolsLayer : Layer
{
private IFrameworkDependencyResolver _resolver;
private IConfigurationService _configService;
public ProtocolsLayer(IFrameworkDependencyResolver resolver, IConfigurationService configurationService)
{
_resolver = resolver;
_configService = configurationService;
}
void HandleConnection1()
{
// What I have at the moment (terrible):
// Resolve the fitting services (All keyed - key is received by the type, Resolve and ResolveWithParameters used here are my wrappers)
var agent = _resolver.Resolve<IFramingAgent>(typeof(Protocol1FramingAgent));
var algo = _resolver.Resolve<IFramingAlgorithm>(typeof(Protocol1FramingAlgorith));
var parser = _resolver.Resolve<IFramingParser>(typeof(Protocol1FramingParser));
// A parameter I get and pass to each protocol at runtime
var protocolConfig = _configService.GetConfig<Protocol1Configuration>();
// Finally resolve the protocol with it's parameters:
protocol = _resolver.ResolveWithParameters<IProtocol>(typeof(Protocol1), new List<object>{
agent, resolver, parser, protocolConfig
});
//...
// Theres gotta be a better way!!
}
void HandleConntection2()
{
// Same as in protocol1
}
void HandleConnection3()
{
// Same as in protocol1
}
}
Take in mind that I don't want references to autofac, meaning I can't use IIndex<> which I heard off.
Thanks!
I made a sample to reproduce your issue : https://dotnetfiddle.net/WOGwoD
If I summarize, your issue is that Autofac Resolve for only thread at a time.
Let take another code sample to reproduce the issue :
class Foo1
{
public Foo1()
{
Console.WriteLine("begin Foo1");
Thread.Sleep(1000);
Console.WriteLine("end Foo1");
}
}
class Foo2
{
public Foo2()
{
Console.WriteLine("begin Foo2");
Thread.Sleep(1000);
Console.WriteLine("end Foo2");
}
}
public class Program
{
public static void Main(string[] args)
{
ContainerBuilder builder = new ContainerBuilder();
builder.RegisterType<Foo1>().AsSelf().SingleInstance();
builder.RegisterType<Foo2>().AsSelf().SingleInstance();
IContainer container = builder.Build();
var t1 = Task.Run(() => container.Resolve<Foo1>());
var t2 = Task.Run(() => container.Resolve<Foo2>());
Task.WaitAll(t1, t2);
}
}
The output of this program is the following :
begin Foo1
end Foo1
begin Foo2
end Foo2
If you change the lifetime scope from SingleInstance to InstancePerDependency (the default one) for a single registration, the output will be :
begin Foo1
begin Foo2
end Foo1
end Foo2
We can see that Autofac lock the IContainer for Shared registration while it is activating a Shared registration.
The lock statement is Line 258 of LifetimeScope.cs.
I think this behavior is here to prevent issue with complex dependency graph. ie : What happens if Foo1 has a nested dependency on Foo2 ?
You won't be able to bypass this behavior of Autofac.
To change this behavior, you will need to change the way your code works. A constructor is not intended to take time. I recommend you to change your constructor to do only required things, if some of initialization process takes time I would defer it or refactor the code to ensure that constructor takes only few milliseconds to complete.
I created a wrapper class to abstract away all the autofac dlls
Your core code should not rely on dependency injection component. In your case, it looks like you use the IFrameworkDependencyResolver interface to lazy load component or to have a factory component. You should rely on Lazy<T> of Func<T> instead. See implicit relation type for more information.
I follow the same strategy in my application to wrap DI library with my classes to have ability to change it later on if I need to.
I followed the same approach, with only one difference
in your code you create ContainerBuilder in your class constructor and keep reference to it, this is the problem
instead, you may need remove away the ContainerBuilder instance, and just depend on Autofac.ILifetimeScope as constructor dependency for your FrameworkDependencyResolver, this dependency will be just injected by autofac runtime with correct lifetime scope.
then at any level on your code, you can just depend on FrameworkDependencyResolver as you need
EDIT
after i saw your update, i would recommend that you separate registration of your service from resolving instances, i.e make new class like FrameworkDependencyRegister and keep the other one for resolving and follow the steps answer above
in my opinion abstracting registration might be too much unneeded abstraction, you can just write one method to do this stuff using normal autofac APIs
Related
I have following registration of the service:
For<Internal.FullPdfExporter>().Use<Internal.FullPdfExporter>();
I have a exporter factory to create different exporters. First of all injected StructureMap container to this factory:
private readonly IContainer _container;
public ExporterFactory(IContainer container)
{
_container = container;
}
Then i use following code to get a instance of FullPdfExporter:
private IExporterBase CreateInstance(Type exporterType)
{
return _container.GetInstance(exporterType) as IExporterBase ;
}
But this code doesn't return control at all. What's the problem is here?
I tried to check all registered instances in debug, and notices that container has registration for "Internal.FullPdfExporter".
Note: Internal is a alias for namespace;
How i get exporter from factory (code of business service which is called from Http Controller):
var task = Task.Run(async () =>
{
foreach (var item in exportData.OrderBy(x => x.ExportUid))
{
var exporter = _exporterFactory.GetBookExporter(param1, param2);
await exporter.StartExport(item.ExportUid);
if (!exporter.IsCompletedSuccessfully)
{
break;
}
}
});
return response;
Note: If to place _exporterFactory.GetBookExporter call before the task.Run, everything works good. Container is able to resolve the dependency.
Code of the GetBookExporter method:
public IExporterBase GetBookExporter(BookSchema bookSchema, PublishProfileType publishProfileType)
{
return CreateInstance(typeof(Internal.FullPdfExporter));
}
Your general logic is flawed. You expect things to run, even after your http call is already over.
Once you return a response, things happen in the ASP.NET framework.
Dependency injection containers finish their scope, objects get disposed.
Keeping those references that are probably scoped or transient in nature until after the call has completed is not going to work. Granted, sometimes it might work, when you have classes that do not implement IDisposable or you just get lucky with a microsocond timing, but generally speaking, this is not anticipated and not meant to work.
If you want to do work after sending out the reply, you have to hand this work over to another party. Maybe you save it into a database and another service picks it up and works on it. Or maybe you have another program or thread running and you try some IPC. But you should not expect threads or tasks referencing things from the scope of your http call to work after it's done.
How to replicate this code with Autofac syntax?
public static class MenuConfig
{
public static void Initialize()
{
var _menuService = DependecyFactory.GetInstance<IMenuService>();
Parameters.Menu = _menuService.Menu();
}
}
Before calling this a "duplicate question" please note that I'm looking for an Autofac command. I CANNOT inject the interface anywhere and then call "Resolve". What I need to is perform an "InstancePerRequest" inline and uninjected so I don't have to do this:
var _service = new Service(new Dependency(new context()));
LightInject has a method that allows instantiation from an interface OUTSIDE of a constructor like this:
var _service = DependecyFactory.GetInstance<IService>();
What is the equivalent method for Autofac?
When calling containerBuilder.Build() you get back a container which implements IContainer and ILifetimeScope, whenever you get hold of one of these interfaces, you can resolve types from it:
container.Resolve<IService>();
If you want this container to be static, you could add the container as a static property to the Program or Startup class (depending if you're creating a Console or ASP.NET application).
Remember that the root container will be around for the entire duration of your application, so this can result in unwanted memory leaks when used incorrectly. Also see the warning in the documentation.
Still, it's perfectly possible to do the memory management yourself by resolving an Owned<> version from your interface:
using (var service = Program.Container.Resolve<Owned<IService>>())
{
service.Value.UseService();
}
Anyway, since you mention a static class in the comments, the best solution is to change that into a non-static class and register it as a singleton with Autofac. Then you can inject a Func<Owned<IService>> serviceFactory into that singleton and create/dispose an instance of the service wherever you need it.
using (var service = serviceFactory())
{
service.Value.UseService();
}
This is simply not possible with Autofac. All other solutions involving Autofac will require code refactoring which may potentially break software functionality. So unfortunately, the most elegant and least disruptive solution is this:
var _service = new Service(new Dependency(new context()));
Since this is an edge case addressing only one part of the software, this compromise is acceptable. It would be nice, however, if Autofac implemented this functionality in some future release.
I have an application that creates a lifetime scope at some point like so:
public class Main
{
public void Main()
{
using (ILifetimeScope scope = AutofacContainer.Container.BeginLifetimeScope())
{
scope.Resolve<SomeClass>();
}
}
}
Within SomeClass I have logic which then calls a lot of different classes and so on..
Then, about 10 methods down the call stack I need to use the main scope to do this:
public class ActivatorFactory : IActivatorFactory
{
public T Create<T>(Type instance)
{
using (ILifetimeScope scope = AutofacContainer.Container.BeginLifetimeScope())
{
return (T)scope.Resolve(instance);
}
}
}
The problem with that is that now I've created a new scope which is just used to resolve a runtime type. I want to be able to use the main scope to resolve this type. How can I do so without passing the main scope down to this factory class through 10 different methods/functions?
The only "hacky" solution I thought of is to just have a static property on my ActivatorFactory and set the scope in my Main class like so:
public class Main
{
public void Main()
{
using (ILifetimeScope scope = AutofacContainer.Container.BeginLifetimeScope())
{
ActivatorFactory.Scope = scope;
scope.Resolve<SomeClass>();
}
}
}
Is there a cleaner solution to use the main scope in another part of my application?
I had this need for a CancellationTokenSource instance per lifetime scope, where children are linked to their parent. If the the root scope's CancellationTokenSource, is canceled, all children lifetime scope's CancellationToken are canceled. To accomplish this, I created:
private sealed class ParentLifetimeScopeAccessor
{
private readonly ILifetimeScope _lifetimeScope;
public ParentLifetimeScopeAccessor(ILifetimeScope lifetimeScope)
{
_lifetimeScope = lifetimeScope;
_lifetimeScope.ChildLifetimeScopeBeginning += OnChildLifetimeScopeBeginning;
}
public ILifetimeScope ParentLifetimeScope { get; private set; }
private void OnChildLifetimeScopeBeginning(object sender, LifetimeScopeBeginningEventArgs e) =>
e.LifetimeScope.Resolve<ParentLifetimeScopeAccessor>().ParentLifetimeScope = _lifetimeScope;
}
With a registration, you can now access your parent's scope:
builder.RegisterType<ParentLifetimeScopeAccessor>().InstancePerLifetimeScope();
With the parent lifetime scope accessor, linked CancellationTokenSource instances can be created:
private static CancellationTokenSource CancellationTokenSourceFactory(IComponentContext context)
{
var scopeAccessor = context.Resolve<ParentLifetimeScopeAccessor>();
var parentScope = scopeAccessor.ParentLifetimeScope;
return null == parentScope
? new CancellationTokenSource()
: CancellationTokenSource.CreateLinkedTokenSource(parentScope.Resolve<CancellationTokenSource>().Token);
}
CancellationToken resolver:
private static CancellationToken CancellationTokenResolver(IComponentContext context) =>
context.Resolve<CancellationTokenSource>().Token;
Two registrations:
builder.Register(CancellationTokenSourceFactory).AsSelf().InstancePerLifetimeScope();
builder.Register(CancellationTokenResolver).AsSelf().InstancePerDependency();
If you're not using ActivatorFactory for your app (and you shouldn't be if you're using inversion of control) then delete it and think about what you're trying to test.
Are you trying to test that you can generally just resolve things from Autofac? Autofac has a raft of unit tests as well as millions of successful users. No value in testing the framework.
Are you trying to test that you registered all the things you needed to register? There's not a lot of value in that, either, for a couple of reasons: first, you'll hit that at runtime pretty quickly and see it in those tests; second, in a large, decoupled system those tests get really stale really quickly. It's a maintenance hassle.
Are you trying to test that a specific object graph can be composed based on your registrations? I might buy this one. See below.
Let's say it's the last thing - you have a really complex and troublesome object graph you want to ensure you can create because people keep breaking it. I could see that.
Separate your registrations out into an Autofac module. Use the Autofac module to test.
public class MyRegistrations : Autofac.Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterType<Thing>();
// and all your other registrations.
}
}
then in the unit test
var builder = new ContainerBuilder();
builder.RegisterModule<MyRegistrations>();
var container = builder.Build();
var thing = container.Resolve<Thing>();
// Assert on the resolved thing.
You can use that same module to encapsulate your registrations in the app and then you'll actually be testing the complex registration but without a factory you're not using.
Warning: It is a slippery slope between testing some complex registration and testing all registrations. Like I said, you really don't want to test every registration you have. I've fallen down this slope. It's a maintenance nightmare. Add a registration to the module/app, add a test. Uh oh, we refactored, now the registrations are all different. Ugh. That's less testing about behavior than about characterization (not "what do I want it to do" but "what does it do now"). Pain. Suffering.
If you are using ActivatorFactory in your app for, say, service location instead of using some more standard thing like CommonServiceLocator that already does that for you and for which Autofac already directly integrates... then just test ActivatorFactory with a real container but with some arbitrary test registrations rather than the whole set from the real app. The functionality of ActivatorFactory doesn't have any bearing on what's registered inside it.
And, yeah, if you're using ActivatorFactory and need to keep it around, you'll have to hand it an ILifetimeScope at app startup. That's how service locators work. You'll see that all over in the Autofac docs when you look at how to integrate with apps like ASP.NET, WCF, and others.
I have multiple services, each of which have a UnitOfWork injected into the constructor using the Simple Injector IoC container.
Currently I can see each UnitOfWork instance is a separate object, this is bad as i am using Entity Framework and require the same context reference across all units of work.
How can I ensure the same UnitOfWork instance is injected into all services per each resolve request? My UnitOfWor will be saved by an external command handler decorator after the command completes.
Please note, this is a common library and will be used for both MVC and Windows Forms, it would be nice to have a generic solution for both platforms if possible.
Code is below:
// snippet of code that registers types
void RegisterTypes()
{
// register general unit of work class for use by majority of service layers
container.Register<IUnitOfWork, UnitOfWork>();
// provide a factory for singleton classes to create their own units of work
// at will
container.RegisterSingle<IUnitOfWorkFactory, UnitOfWorkFactory>();
// register logger
container.RegisterSingle<ILogger, NLogForUnitOfWork>();
// register all generic command handlers
container.RegisterManyForOpenGeneric(typeof(ICommandHandler<>),
AppDomain.CurrentDomain.GetAssemblies());
container.RegisterDecorator(typeof(ICommandHandler<>),
typeof(TransactionCommandHandlerDecorator<>));
// register services that will be used by command handlers
container.Register<ISynchronisationService, SynchronisationService>();
container.Register<IPluginManagerService, PluginManagerService>();
}
The desired outcome of the below line is to create a object which has a shared UnitOfWork instance throughout the constructed object graph:
var handler = Resolve<ICommandHandler<SyncExternalDataCommand>>();
Here are my services:
public class PluginManagerService : IPluginSettingsService
{
public PluginManagerService(IUnitOfWork unitOfWork)
{
this.unitOfWork = unitOfWork;
}
private readonly unitOfWork;
void IPluginSettingsService.RegisterPlugins()
{
// manipulate the unit of work
}
}
public class SynchronisationService : ISynchronisationService
{
public PluginManagerService(IUnitOfWork unitOfWork)
{
this.unitOfWork = unitOfWork;
}
private readonly unitOfWork;
void ISynchronisationService.SyncData()
{
// manipulate the unit of work
}
}
public class SyncExternalDataCommandHandler
: ICommandHandler<SyncExternalDataCommand>
{
ILogger logger;
ISynchronisationService synchronisationService;
IPluginManagerService pluginManagerService;
public SyncExternalDataCommandHandler(
ISynchronisationService synchronisationService,
IPluginManagerService pluginManagerService,
ILogger logger)
{
this.synchronisationService = synchronisationService;
this.pluginManagerService = pluginManagerService;
this.logger = logger;
}
public void Handle(SyncExternalDataCommand command)
{
// here i will call both services functions, however as of now each
// has a different UnitOfWork reference internally, we need them to
// be common.
this.synchronisationService.SyncData();
this.pluginManagerService.RegisterPlugins();
}
}
Which registration you need depends on the type of application. Since you are talking about two different frameworks (MVC and WinForms), both will have a different registration.
For an MVC application (or web applications in general), the most common thing to do is to register the unit of work on a per web request basis. For instance, the following registration will cache the unit of work during a single web request:
container.Register<IUnitOfWork>(() =>
{
var items = HttpContext.Current.Items;
var uow = (IUnitOfWork)items["UnitOfWork"];
if (uow == null)
{
items["UnitOfWork"] = uow = container.GetInstance<UnitOfWork>();
}
return uow;
});
The downside of this registration is that the unit of work is not disposed (if needed). There is an extension package for the Simple Injector that adds RegisterPerWebRequest extension methods to the container, which will automatically ensure that the instance is disposed at the end of the web request. Using this package, you will be able to do the following registration:
container.RegisterPerWebRequest<IUnitOfWork, UnitOfWork>();
Which is a shortcut to:
container.Register<IUnitOfWork, UnitOfWork>(new WebRequestLifestyle());
A Windows Forms application on the other hand, is typically single threaded (a single user will be using that application). I believe it is not unusual to have a single unit of work per form, which is disposed the form closes, but with the use of the command/handler pattern, I think it is better to take a more service oriented approach. What I mean by this is that it would be good to design it in such way that you can move the business layer to a WCF service, without the need to make changes to the presentation layer. You can achieve this by letting your commands only contain primitives and (other) DTOs. So don't store Entity Framework entities into your commands, because this will make serializing the command much harder, and it will lead to surprises later on.
When you do this, it would be convenient to create a new unit of work before the command handler starts executing, reuse that same unit of work during the execution of that handler, and commit it when the handler completed successfully (and always dispose it). This is a typical scenario for the Per Lifetime Scope lifestyle. There is an extension package that adds RegisterLifetimeScope extension methods to the container. Using this package, you will be able to do the following registration:
container.RegisterLifetimeScope<IUnitOfWork, UnitOfWork>();
Which is a shortcut to:
container.Register<IUnitOfWork, UnitOfWork>(new LifetimeScopeLifestyle());
The registration however, is just half of the story. The second part is to decide when to save the changes of the unit of work, and in the case of the use of the Lifetime Scope lifestyle, where to start and end such a scope. Since you should explicitly start a lifetime scope before the command executes, and end it when the command finished executing, the best way to do this, is by using a command handler decorator, that can wrap your command handlers. Therefore, for the Forms Application, you would typically register an extra command handler decorator that manages the lifetime scope. This approach does not work in this case. Take a look at the following decorator, but please note that it is incorrect:
private class LifetimeScopeCommandHandlerDecorator<T>
: ICommandHandler<T>
{
private readonly Container container;
private readonly ICommandHandler<T> decoratedHandler;
public LifetimeScopeCommandHandlerDecorator(...) { ... }
public void Handle(T command)
{
using (this.container.BeginLifetimeScope())
{
// WRONG!!!
this.decoratedHandler.Handle(command);
}
}
}
This approach does not work, because the decorated command handler is created before the lifetime scope is started.
We might be tempted into trying to solve this problem as follows, but that isn't correct either:
using (this.container.BeginLifetimeScope())
{
// EVEN MORE WRONG!!!
var handler = this.container.GetInstance<ICommandHandler<T>>();
handler.Handle(command);
}
Although requesting an ICommandHandler<T> inside the context of a lifetime scope, does indeed inject an IUnitOfWork for that scope, the container will return a handler that is (again) decorated with a LifetimeScopeCommandHandlerDecorator<T>. Calling handler.Handle(command) will therefore result in a recursive call and we'll end up with a stack overflow exception.
The problem is that the dependency graph is already built before we can start the lifetime scope. We therefore have to break the dependency graph by deferring building the rest of the graph. The best way to do this that allows you to keep your application design clean] is by changing the decorator into a proxy and injecting a factory into it that will create the type that it was supposed to wrap. Such LifetimeScopeCommandHandlerProxy<T> will look like this:
// This class will be part of the Composition Root of
// the Windows Forms application
private class LifetimeScopeCommandHandlerProxy<T> : ICommandHandler<T>
{
// Since this type is part of the composition root,
// we are allowed to inject the container into it.
private Container container;
private Func<ICommandHandler<T>> factory;
public LifetimeScopeCommandHandlerProxy(Container container,
Func<ICommandHandler<T>> factory)
{
this.factory = factory;
this.container = container;
}
public void Handle(T command)
{
using (this.container.BeginLifetimeScope())
{
var handler = this.factory();
handler.Handle(command);
}
}
}
By injecting a delegate, we can delay the time the instance is created and by doing this we delay the construction of (the rest of) the dependency graph. The trick now is to register this proxy class in such way that it will inject the wrapped instances, instead of (of course) injecting itself again. Simple Injector supports injecting Func<T> factories into decorators, so you can simply use the RegisterDecorator and in this case even the RegisterSingleDecorator extension method.
Note that the order in which decorators (and this proxy) are registered (obviously) matters. Since this proxy starts a new lifetime scope, it should wrap the decorator that commits the unit of work. In other words, a more complete registration would look like this:
container.RegisterLifetimeScope<IUnitOfWork, UnitOfWork>();
container.RegisterManyForOpenGeneric(
typeof(ICommandHandler<>),
AppDomain.CurrentDomain.GetAssemblies());
// Register a decorator that handles saving the unit of
// work after a handler has executed successfully.
// This decorator will wrap all command handlers.
container.RegisterDecorator(
typeof(ICommandHandler<>),
typeof(TransactionCommandHandlerDecorator<>));
// Register the proxy that starts a lifetime scope.
// This proxy will wrap the transaction decorators.
container.RegisterSingleDecorator(
typeof(ICommandHandler<>),
typeof(LifetimeScopeCommandHandlerProxy<>));
Registering the proxy and decorator the other way around would mean that the TransactionCommandHandlerDecorator<T> would depend on a different IUnitOfWork than the rest of the dependency graph does, which would mean that all changes made to the unit of work in that graph will not get committed. In other words, your application will stop working. So always review this registration carefully.
Good luck.
I'm writing a task-execution engine and I'm running into some questions about what is the appropriate way to insure that everything is properly released when I'm using Castle.Windsor (ver 2.5.1.0) in a Task-Parallels-Library system.
I've included a highly simplified pseudo-code example of what I'm doing at the end of the post.
Here are my questions
Castle.Windsor does not have a "PerTask" lifestyle and given the way the TPL uses threads, I believe the PerThread lifestyle won't work. So what is the appropriate lifestyle?
If I force TPL to be a Task-Per-Thread mechanism, it's my understanding that calling Release on a PerThread lifestyle won't actually release anything until the container is disposed of, and currently I only have a single container that lives forever. Is there a better way to set up my containers to support PerThread?
In the example below, I've also indicated three potential places where I can call release on the container. According to most of what I've read, I should rarely need to call release myself, but if I don't call it at those places, how do those registrations get disposed of?
The Service:
class Service : ServiceBase
{
IWindsorContainer _container;
Engine _engine;
public Service()
{
_container = new WindsorContainer();
_container.Register(Component.For<Engine>().ImplementedBy<Engine>().LifeStyle.Singleton);
_container.Register(Component.For<ISession>().UsingFactoryMethod(() => SessionFactory.Get());
_container.Register(Component.For<IDataAccess>().ImplementedBy<SqlDataAccess>());
_container.Register(Component.For<IWorker>().ImplementedBy<DocumentWorker>());
_container.Register(Component.For<IDependency>().ImplementedBy<SomeDependency>());
}
protected override void OnStart(string[] args)
{
_engine = _container.Resolve<Engine>();
_engine.Start();
}
protected override void OnStop()
{
_container.Release(_engine); //1?
}
}
The "Engine":
class Engine
{
IWindsorContainer _container
public Engine(IWindsorContainer container)
{
_container = container;
}
public void Start()
{
Task.Factory.StartNew(() => Work());
}
public void Work()
{
var worker = _container.Resolve<IWorker>();
worker.DoWork();
_container.Release(worker); //2?
}
}
A Worker Task:
class Worker : IWorker
{
IDataAccess _accessor;
IWindsorContainer _container;
public Worker(IDataAccess accessor, IWindsorContainer container)
{
_accessor = accessor;
_container = container;
}
public void DoWork()
{
var depen = _container.Resolve<IDependency>();
//DoWork
_container.Release(depen); //3?
}
}
Thanks, I'll be happy to elaborate further if more detail is needed.
I know in most cases Castle Windsor Recommends 1 Conatiner per app Domain, however you can have as many as you want. There are IOC design Patterns where multiple containers are used, such as 1 container per dll. In this senario you may want one container per thread or process and one for the rest of the application. Hope this helps
My experience is that setting up a container is rather costly, which is fine as it's usually a one time experience.
But if we do it per Task, like mentionned here, we lose the performance gain, we probably wanted by using Tasks.
I'm strugling a bit with this as well. I'm using HybridPerWebRequest/Thread lifestyles as most of the components are shared and I don't want instantiators needing to know the inner details of the lower levels, so they should use the Castle Installers I'm giving them.
The problem I now have is also related to the fact that Per Task creation isn't really supported, so I lose some of my "StateFull" Services when the newly spawned task is not using the same thread as the main thread.
Castle will work fine, as it will generate a new object. But in this case I lose the State of the main thread.
I'm thinking of making it less formante by dropping the Task Creation.