Autofac heavy Initialize task - c#

Is there a way with Autofac DI to add an initialize method that will run on a different thread for a registered component?
Instead of having this:
public class Service
{
public Service()
{
// Heavy init task
}
}
Have this:
public class Service
{
public Service()
{
// No logic
}
// This should run on different thread when Service is created
public void Init()
{
// Heavy init
}
}

You can register using a lambda expressions, in which you can add code. Then you can start a task that calls the init-method.
Something like this:
builder.Register(c => {
var instance = new Service();
new Task(() => instance.Init()).Start();
return instance;
}).As<IService>().SingleInstance();

I guess not.
The problem is that Autofac is probably needed to initialize everything comes after the service startup: repository, engines, and so on. What about if you need a component to continue the service work but Autofac is still in the middle of the initialization process? You have to stop processing the service, wait for Autofac to continue, and then start the process again... well, it's like a normal startup process.
One possible options is to user the Autofac IStartable components. Check this answer for more details.
You can for example immediately load everything you need for the "service" startup, and demand to the startable section everything is not immediately required (a kind of lazy loading). Then you can do something like this:
var newBuilder = new ContainerBuilder();
newBuilder.Register...;
newBuilder.Update(existingContainer);
to update the container with the other components.
Hope it helps :)

Related

Why StructureMap container doesn't return the control then calling GetInstance?

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 resolve from autofac parent scope without passing it around multiple times?

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.

When to compose application root in a windows service

Given a C# console application that will run as a windows service, there are sort of 2 application entry points. The first obvious one is the static void Main method. Part of the job of this method is to install something that extends ServiceBase and then run it to get its OnStart method to be invoked. There are also higher level tools like Topshelf that help you avoid lower level ServiceBase implementations, but still, you end up with 2 potential application entry points: static void Main, and some kind of OnStart method.
Should the application root for such a service be composed within the service's OnStart method, or earlier than that as part of static void Main?
It seems that there could be an advantage to composing within the service's OnStart method (and destroying / disposing it in the OnStop method) since restarting a service would then compose a new application root. The only real disadvantage I can see here is that if I am using a tool like Topshelf, I can't use the DI container to obtain an instance of my Service class. Then again, that's probably not a real disadvantage. Still, most of the applications I read compose the root during Main, not during OnStart, and I'm not sure why.
Is one approach really better than the other, or does it depend, and my question is really an opinion-based one?
I think it's more an opinion than a fact, but I prefer to compose during service building and then use OnStart() to activate the service I composed before. This is the way I usually work (with Topshelf). For example:
program.cs
public class Program
{
private static ILifetimeScope _scope;
private static readonly ILog Log = LogManager.GetLogger(typeof(Program));
public static void Main(string[] args)
{
try
{
XmlConfigurator.Configure();
// configure composition
_scope = CompositionRoot.CreateScope();
HostFactory.Run(x =>
{
x.UseLog4Net();
x.UseAutofacContainer(_scope);
x.Service<IMyService>(svc =>
{
svc.ConstructUsingAutofacContainer();
svc.WhenStarted(tc => tc.Start());
svc.WhenStopped(tc =>
{
tc.Stop();
_scope.Dispose();
});
});
x.RunAsNetworkService();
x.StartManually();
});
}
catch (Exception e)
{
Log.Error("An error occurred during service construction.", e);
throw;
}
}
}
composition.cs
internal class CompositionRoot
{
public static ILifetimeScope CreateScope()
{
var builder = new ContainerBuilder();
builder.RegisterType<MyService>().As<IMyService>().SingleInstance();
// other things you want to register
return builder.Build();
}
}
imyservice.cs
public interface IMyService
{
void Start();
void Stop();
}
The only real disadvantage I can see here is that if I am using a tool like Topshelf, I can't use the DI container to obtain an instance of my Service class
This is true, but you don't need to access the program.cs code, just the MyService code, which will represent the actual "core" code of your service.
Also when you stop the service you will actually kill it (unless you pause it), so the composition will be executed again, no matter if you put it inside the "onStart()" or not.
As usual, IMHO. :)

Autofac multithreading issues

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

C#, .NET and IoC with Ninject: how to warm up instances of classes that take long to create?

I have IOC from Ninject in my app. There are a couple classes that take significant time to initialize (some static data caches fetched from DB or files). Apparently they need to be created before handling the very first user request. Otherwise there is a high risk of timeouts. Does Ninject provide a way to tell the Kernel to go thru bindings and create some?
You can create those instances and pass them with WithConstructorArgument for all dependents when you wire up your app. Quite weird, I must admit, but will work.
var heavy = new HeavyDependency();
Bind<SomeInterface>().To<SomeClass>().WithConstructorArgument("HeavyDependency", heavy );
You can hide the dependency behind a proxy and load it in the background:
public class LazyHeavyDependency : IHeavyDependency
{
private readonly Lazy<IHeavyDependency> lazy;
public LazyHeavyDependency(Lazy<IHeavyDependency> lazy)
{
this.lazy = lazy;
}
void IHeavyDependency.DoWork()
{
this.lazy.Value.DoWork();
}
}
You can wire it up like this:
var lazyDependency = new Lazy<IHeavyDependency>(() =>
new RealHeavyDependency());
Bind<IHeavyDependency>()
.ToConstant(new LazyHeavyDependency(lazyDependency));
// Load value in a background thread.
Task.Factory.StartNew(() => lazy.Value);

Categories