Change implementation of ninject dependency after singleton instantiation - ninject

So, I have a viewmodel class in a xamarin project that I inject some dependencies into via ninject binding on app start. One of these is an IDialogService.
When my MainPage in my application changes it raises a property changed event and I rebind the implementation of the dialog service since it is tied to the MainPage.
If my viewmodel has already been created with lets say DialogServiceA and then when MainPage changes we rebind to DialogServiceB, will my viewmodel be using service A or B? I think it is using A and therefore does not display in the UI because it is tied to a MainPage that no longer exists.
So, if this is the case how can I dynamically change my dialog service but then update classes that have already been instantiated without changing everything to get the current dialog service from the container every time its used (therefore not injecting it at all really, and doing more of a servicelocator)
Also, if this approach is completely wrong, set me straight.

You're right. Re-configuration of the container does not affect already instanciated objects.
If you want to change dependencies without re-instanciating the dependent (parent ViewModel) there's a few possibilities for you:
use a factory to instanciate the service every time. Implement an Abstract Factory (Site by Mark Seeman) or use Ninject.Extensions.Factory to do so
instead of injecting a service directly, inject an adapter. The adapter then redirects the request to the currently appropriate service. To do so, either all service can be injected into the adapter, or you can use a factory as with the possibility above.
instead of inject a service directly, inject a proxy. The proxy is quite similar to the adapter, but instead of coding every method / property redirection specifically, you code a generic redirect by an interceptor. Here's a tutorial on castle dynamic proxy
At the end of the day, however, i believe you'll also need a way to manage when to change the service / which it should be. There's probably a design alternative which doesn't rely on exchanging objects in such a manner.. which would make it an easier (and thus better?) design.
Edit: i just saw that you also tagged the question as xamarin-forms. In that case it most likely won't be an option to use either a dynamic proxy nor ninject.extensions.factory (it relies on dynamic proxies, too). Why? dynamic proxy / IL emitting is not supported on all platforms, AFAIR specifically on Apple devices this can't be done.

Related

Ninject: What happens to non-disposable InRequestScope and InTransientScope objects after the HTTP request is finished?

I have searched a lot about these question, here and a lot of other places, but not getting everything I want to know!
From a WebApi project point-of-view, when are InTransientScope objects Created? In the Ninject docs it is stated that such objects are created whenever requested, but in a web api project that handles HTTP requests, the instance is created at the request start time so in this regard it is the same as InRequestScope then?
In a WebApi project, is it okay to use InTransientScope objects knowing that they will never be kept track of by Ninject? If Ninject never keeps track of Transient objects, then what is the purpose of this scope and what happens to such objects after they have been used?
If I declare an object with InRequestScope and that object doesn't implement the IDisposable interface, what happens to such object after the web request has completed? Will it be treated the same way as an InTransientScope object?
Are different scopes to be used for: WebApi controllers, Repositories(that use a InRequestScope Session that is created separately) and Application services?
There's two purposes for scopes:
Only allow one object to be created per scope
(optionally) dispose of the object once the scope ends.
As said, the disposal is optional. If it doesn't implement the IDisposable interface it's not being disposed. There's plenty of usecases for that.
The InTransientScope is the default scope - the one being used if you don't specify another one. It means that every time a type A is requested from the kernel one activation takes place and the result is returned. The activation logic is specified by the binding part that follows immediately after the Bind part (To<...>, ToMethod(...),...).
However, this is not necessarily at the time the web-request starts and the controller is instanciated. For example, you can use factories or service location (p.Ex. ResolutionRoot.Get<Foo>()) to create more objects after the controller has been created. To answer your questions in short:
When: When a request takes place or whenever your code asks for a type from Ninject either directly (IResolutionRoot.Get(..)) or through a factory. As InTransientScope objects are not being tracked they will not be disposed, however, if they are not disposable and the entire request code requests only one IFoo then practically there's is no discernible difference (apart from the slight performance hit due totracking InRequestScope()-ed objects)
As long as you don't need to make sure that instances are shared and/or disposed this is completely fine. After they are not being used anymore, they will get garbage-collected like any object you would new yourself.
When the scope ends ninject will remove the weak reference to the non-IDisposable object. The object itself will not be touched - just like when bound InTransientScope()
That depends on your specific requirements and implementation details. Generally one needs to make sure that long-scoped objects don't depend on short-scoped objects. For example, a Singleton-Service should not depend on a Request-scoped object. As a baserule, everything should be InTransientScope() unless there's a specific reason why it should not be. The reason will dictate what scope to use...

#RepositoryEventHandler only invoked via HTTP - why?

when I use a #RepositoryEventHandler then its methods are only invoked when the call into the repository comes in via HTTP.
Any reason why? OK, it is called Spring Data REST, but wouldn't it be VERY useful to invoke the handler too, when I call my Repo directly, not via HTTP?
Any way to invoke the handler when called directly (some magic AOP-stuff)?
Thank you
The reason for that is that the different persistence mechanisms covered by the different Spring Data modules already ship with event mechanisms. Depending on the one you use you now get a different mechanism to use.
Unfortunately this can't be unified as e.g. with JPA not all persistence operations need to go through the repository in the first place, as JPA automatically flushes all changes that were made to an attached instance on EntityManager flush. In this case even AOP on the repository instance doesn't help.
So you're basically left with two choices:
The events exposed by Spring Data REST for all repositories (as we basically don't make use of the automatic change tracking in JPA).
The store specific event mechanisms that will make sure that the persistence mechanism exposes events as documented.
I don't know if the solution I put below from other stackoverflow questions would seen as acceptable by #Olivier-drotbohm, but from:
SpringDataRest #RepositoryEventHandler not running when Controller is added
and
#RepositoryEventHandler events stop with #RepositoryRestController
you could inject/autowire the "ApplicationEventPublisher" and fire the BeforeCreateEvent/AfterCreateEvent manually to trigger the RepositoryEventHandler.
This is not a perfect solution, but I hope it is good enough for you (and we tested it: it works).

Ninject provider can't resolve types registered within a named scope

I am using the NamedScoped Ninject extension in an attempt to create object graphs that are constructed everytime a command handler is constructed by the container. In other words, I want a fresh object graph for every command that might get processed by its corresponding handler.
I have used the .DefinesNamedScope("TopLevelOrhcestrator") binding when registering my "command handlers" as they are the top level for command processing.
A type in this named scope needs to be injected with the result of a method call on a type already registered in this named scope. I thought the best way to do this would be with a ninject provider.
Inside the provider I attempt to resolve the type in hopes I can call a method on it to pass into another object I am creating within this named scope. The problem I'm having is that when I ask the IContext for the instance inside the customer provider I get an exception that says "No matching scopes are available, and the type is declared InNamedScope(TopLevelOrchestrator).
context.Kernel.Get<TypeAlreadyRegisteredInScope>().MethodThatGetsAnotherDependency()
Is it possible to get types from the container inside a Ninject provider when they are registered inside a named scope?
EDIT
I apologize if the use case seems a bit odd, I am experimenting with some ideas about how to manage my units of work and other services/managers that may need a handle to the uow to complete a business usecase. I know its common for the unit of work to be "started" and then passed into all dependencies that may need to take part in a larger process. I was thinking I'd rather let my orchestrator take a unit of work factory so that it could deterministically destroy the UOW and it would be clear who the owner of a usecase is. What would get supplied to the managers/services would be a proxy to the unit of work that would be null until a real unit of work was started by the orchestrator. That's why I was attempting to link the proxy from the already registered type in my provider. This is all very experimental at this point and was testing some ideas.
I'd be happy to hear any further thoughts.
For MethodThatGetsAnotherDependency() to be able to .Get<>() an instance that is bound .InNamedScope(...) you will need to add the Context Preservation Extension.
This is because NamedScope is adding a parameter to the request context of the binding that has .DefinesNamedScope(...). As soon as that request is over, that context and it's parameters are forgotten. Now with the ContextPreservation extension the context is kept and reused for late / factory creations (Func<>, interface factory with .ToFactory() binding...). It think it should also work with providers.
If not, just switch to a factory instead of a provider.
However i have to admit that i don't fully understand why/what you are trying to achieve. There might be simpler ways.

Autofac: Is it possible to pass a lifetime scope to another builder?

Problem:
I am building a four layer system with Ui, ServiceLayer, BizLayer and DataLayer. In line with good practice the ServiceLayer hides the BizLayer and DataLayer from the Ui, and of course the ServiceLayer doesn't know what the Ui Layer is.
My implementation is a single .NET application with each layer in its own assembly. I am using Autofac.MVC3 in my MVC3 Ui layer to do all the resolving classes used in a web request. I also include standard Autofac in my ServiceLayer so that it can handle the registration of all other layers in my application. At system startup I call a method to register all the types with Autofac. This does:
Register the lower levels by calling a module inside the ServiceLayer. That handles the registration of itself and all other assemblies using the standard NuGet Autofac package.
Then the Ui layer uses the NuGet Autofac.MVC package to register the various controllers and the IActionInvoker for Action Method injection.
My UnitOfWork class in my DataLayer is currently registered with InstancePerLifetimeScope because it is registered by the ServiceLayer which uses plain Autofac and knows nothing about InstancePerHttpRequest. However I read here that I should use InstancePerHttpRequest scope.
Question:
My question is, can I pass a lifetime scope around, i.e. could the MVC layer pass the InstancePerHttpRequest down to the service layer to use where needed? Alex Meyer-Gleaves seemed to suggest this was possible in his comment from this post below:
It is also possible to pass your own ILifetimeScopeProvider implementation to the AutofacDependencyResolver so that you can control the creation of lifetime scopes outside of the ASP.NET runtime
However the way he suggests seems to be MVC specific as ILifetimeScopeProvider is a MVC extension class. Can anyone suggest another way or is InstancePerLifetimeScope OK?
InstancePerHttpRequestScope is in fact a variant of InstantPerLifetimeScope. The first one only works in a request. If you want to execute some stuff on a background thread, it won't be available.
Like you I'm using autofac in as.net mvc and multiple app layers. I pass around the Container itself for the cases where I need to have a lifetime scope. I have a background queue which executes tasks. Each taks pretty much needs to have its own scope and to be exdecuted in a transaction. The Queue has an instance of IContainer (which is a singleton) and for every task, it begins a new scope and executes the task.
Db access and all are setup as INstancePerLifetimeScope in order to work in this case and I don't have aproblem when I use them in a controller.
With the help of MikeSW, Cecil Philips and Travis Illig (thanks guys) I have been put on the right track. My reading of the various posts, especially Alex Meyer-Gleaves post here, it seems that InstancePerLifetimeScope is treated as InstancePerHttpRequest when resolved by the Autofac.MVC package, within certain limitations (read Alex's post for what those limitations they). Alex's comment is:
Using InstancePerHttpRequest ensures that the service is resolved from the correct lifetime scope at runtime. In the case of MVC this is always the special HTTP request lifetime scope.
This means that I can safely register anything that needs a single instance for the whole htpp request as InstancePerLifetimeScope and it will work fine as long as I don't have child scoped items. That is fine and I can work with that.

Passing client context using Unity in WCF service application

I have a WCF service application (actually, it uses WCF Web API preview 5) that intercepts each request and extracts several header values passed from the client. The idea is that the 'interceptor' will extract these values and setup a ClientContext object that is then globally available within the application for the duration of the request. The server is stateless, so the context is per-call.
My problem is that the application uses IoC (Unity) for dependency injection so there is no use of singleton's, etc. Any class that needs to use the context receives it via DI.
So, how do I 'dynamically' create a new context object for each request and make sure that it is used by the container for the duration of that request? I also need to be sure that it is completely thread-safe in that each request is truly using the correct instance.
UPDATE
So I realize as I look into the suggestions below that part of my problem is encapsulation. The idea is that the interface used for the context (IClientContext) contains only read-only properties so that the rest of the application code doesn't have the ability to make changes. (And in a team development environment, if the code allows it, someone will inevitably do it.)
As a result, in my message handler that intercepts the request, I can get an instance of the type implementing the interface from the container but I can't make use of it. I still want to only expose a read-only interface to all other code but need a way to set the property values. Any ideas?
I'm considering implementing two interfaces, one that provides read-only access and one that allows me to initialize the instance. Or casting the resolved object to a type that allows me to set the values. Unfortunately, this isn't fool-proof either but unless someone has a better idea, it might be the best I can do.
Read Andrew Oakley's Blog on WCF specific lifetime managers. He creates a UnityOperationContextLifetimeManager:
we came up with the idea to build a Unity lifetime manager tied to
WCF's OperationContext. That way, our container objects would live
only for the lifetime of the request...
Configure your context class with that lifetime manager and then just resolve it. It should give you an "operation singleton".
Sounds like you need a Unity LifetimeManager. See this SO question or this MSDN article.