4

I'm currently facing a problem with the asynchronous initialization of an object (this question). I'm using Ninject 3.0.1.10, and I want to achieve the following:

Kernel.Bind<IServiceProvider>().ToMethod(async ctx => await ServiceProvider.CreateAsync())

Now this thing doesn't compile, because async lambda expression returns a Task<ServiceProvider>, not a ServiceProvider. Is there any way to initialize objects asynchronously in Ninject? Maybe some workaround?

Community
  • 1
  • 1
Haspemulator
  • 11,050
  • 9
  • 49
  • 76
  • Have you tried `Task.Wait(/*...*/)`? – Jan P. Apr 10 '13 at 12:44
  • It will be synchronous then... But you're right, this asynchrony has to manifest itself somewhere. I guess, Kernel.Get() then should also be asynchronous. Is it possible in Ninject at all? – Haspemulator Apr 10 '13 at 12:52
  • 1
    There is two ways how you can decouple injection from instanciation of IServiceProvider. The first is: inject Lazy. This is supported by ninject, but means the IServiceProvider consumer then knows about it. The second is binding IServiceProvider to a proxy of the interface, where as the first call on the proxy will have to retrieve the actual instance (or perform it on a Lazy again). However, note that ninject by default creates a proxy per type, not per instance. I have a work around for this. Tell me if you want me to post a complete solution. – BatteryBackupUnit Sep 26 '13 at 12:43
  • @BatteryBackupUnit yes, please post your solution. I guess, some workaround wouldn't hurt, since there's no any answer on this question yet. – Haspemulator Sep 26 '13 at 17:23

1 Answers1

0

As per your request i'm posting a solution which employs ninject. I diverted slightly from your goals as the constructor is not performing the initialization but a method is. The method is called by the interceptor. Async-Ctor is most likely possible by changing to an "interface proxy without target" (see http://docs.castleproject.org/Tools.Kinds-of-proxy-objects.ashx) and having the interceptor instanciate the object.

I also want to say that i believe async-initialization probably will provide more downsides than benefits. For example, it will be difficult to handle initialization exceptions, since any call on the interface may result in an initialization exception.

Castle Dynamic Proxy + Interceptor which initializes target async

IFoo is bound to InterceptingProxyProvider : IProvider. The provider instanciates Foo, all interceptors for Foo, and then creates and returns a castle dynamic proxy (Proxy). This is what Caller receives when IFoo is being injected. The AsyncInitializationInterceptor starts initialization of Foo in it's constructor. Upon the first intercepted call, it waits for initialization to complete, then proceeds. In case initialization fails with an exception, all further access to IFoo will result in the initialization exception being thrown.

On a further note, the ninject proxy extension creates an interceptor instance per target type. However, what we want is one interceptor instance per target instance. This is why i provided a custom implementation of binding & instanciation of the proxy & interceptors.

Here is the code, complete with integration tests which should show you how to use it:

BatteryBackupUnit
  • 12,934
  • 1
  • 42
  • 68
  • Could someone post the answer in code?. I'm unable to access both those urls, and I really would like to use an async lib with ninject. – Beau Trepp May 21 '15 at 07:01
  • The solution consists of quite a few source files. I could add them to the answer but it would mean you would have to add quite a lot of files to a solution/c# project. Instead, i could also upload it to another file hoster - in case there's one you can access? Just let me know. – BatteryBackupUnit May 21 '15 at 10:43
  • It thats the case, perhaps a github repo would be best?. Most file sharing sites are blocked by IT here, but github is okay. Thank you for your response. I was also mainly after looking at the rough implementation. If it's a whole bunch of files maybe it is a github repo/nuget package instead :) – Beau Trepp May 22 '15 at 01:42
  • @user1570690 github Repo is now available: https://github.com/BrunoJuchli/NinjectAsyncInitializationByInterception – BatteryBackupUnit May 22 '15 at 05:07