I'm trying to change the concrete type at run-time for a type registered during startup. I'm able to update the container & service locator. But already existing view models still have reference to the original service bootstrapped.
Bootstrap Code:
container.RegisterInstance<IMyService>(new MyServiceA(), new ContainerControlledLifetimeManager());
ViewModelCode:
public ViewModel(IMyService service)
{
_service = service;
}
Service Changing Code:
container.RegisterInstance<IMyService>(new MyServiceB(), new ContainerControlledLifetimeManager());
serviceLocator.Resolve returns MyServiceB. MyServiceA no longer exists in the container. But existing view models still have reference to MyServiceA.
Is there any way to have updates to the container update existing/resolved references?
UPDATE:
Maybe this unit test can help understand the behavior I'm fighting.
using Microsoft.VisualStudio.TestTools.UnitTesting;
using Microsoft.Practices.Unity;
namespace UnitTestProject1
{
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestUnity()
{
// register ServiceA and ViewModel
var container = new UnityContainer();
container.RegisterType<IMyService, MyServiceA>();
container.RegisterType<MyViewModel>();
// resolve viewmodel
var viewModel = container.Resolve<MyViewModel>();
// replace ServiceA with ServiceB
container.RegisterInstance<IMyService>(new MyServiceB());
// Assert success, IMyService is MyServiceB
Assert.AreEqual(container.Resolve<IMyService>().GetType(), typeof(MyServiceB));
// Assert fails viewmodel still using MyServiceA
Assert.AreEqual(viewModel.RegisteredService.GetType(), typeof(MyServiceB));
}
}
public interface IMyService
{
}
public class MyServiceA : IMyService
{
}
public class MyServiceB : IMyService
{
}
public class MyViewModel
{
public IMyService RegisteredService { get; }
public MyViewModel(IMyService myService)
{
RegisteredService = myService;
}
}
}
If you'll implement Proxy-class for IMyService which'll retrieve the actual implementation from ServiceLocator per each call the problem will be solved:
public class MyServiceProxy : IMyService
{
public int DoWork(string someParameter)
{
return ServiceLocator.Resolve<IMyService>().DoWork(someParameter);
}
}
Now you can inject MyServiceProxy to your class constructor. The other way is to add an explicit call of ServiceLocator to each IMyService usage. But you should remember that ServiceLocator can make your code more complicated to understand because it hides class dependences.
UPDATE
Situation with bindings to the retrieved data reminds the reaction to the event. When event "Data source changed" raises in your system the subscribers (ViewModels) sholud handle this event. It's work for EventAggregator class which has implementation in Prism.
Then the solution based on 2 parts:
Subscribe your ViewModels which uses IMyService to MyServiceChangedEvent (first you should implement it). In the handlers you can change implementation via ServiceLocator or via event parameters, raise PropertyChanged for update databinding and do another actions for your cases.
public class MyServiceChangedEvent : CompositeWpfEvent<IMyService>
{
}
Publish new MyServiceChangedEvent on IMyService changed. You can create new property inside your event to pass new implementation to your subscribers instead of using ServiceLocator.
var newMyService = new MyServiceB();
container.RegisterInstance<IMyService>(newMyService, new ContainerControlledLifetimeManager());
eventAggregator.GetEvent<MyServiceChangedEvent>().Publish(newMyService);
Why don't you just use named instances?
_container.RegisterType<IMyService, MyService>("ServiceA", new ContainerControlledLifetimeManager());
_container.RegisterType<IMyService, MyOtherService>("ServiceB", new ContainerControlledLifetimeManager());
_container.Resolve<IMyService>("ServiceA");
Related
I want to take advantage of dependency injection in my Xamarin project but can't get constructor injection to work in C# classes behind XAML views. Is there any way to do it ?
I've seen guides how to setup dependency injections in View Models, to later use them as repositories but that doesn't work for me.
So far I tried Ninject and Unity.
Code:
This is the service I want to use inside of my PCL project:
public class MyService : IMyService
{
public void Add(string myNote)
{
//Add Note logic
}
}
Interface:
public interface IMyService
{
void Add(string myNote);
}
Unity setup in App.Xaml:
public App ()
{
InitializeComponent();
var unityContainer = new UnityContainer();
unityContainer.RegisterType<IMyService, MyService>();
var unityServiceLocator = new UnityServiceLocator(unityContainer);
ServiceLocator.SetLocatorProvider(() => unityServiceLocator);
MainPage = new MainMasterMenu(); //<-- feel that I'm missing something here as I shouldn't be creating class instances with DI, right ?
}
Usage that I'd like to see. This is .CS file behind a XAML starting page:
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class MainMasterMenu : MasterDetailPage
{
private IMyService _myService;
public MainMasterMenu(IMyService myService)
{
_myService = myService
}
private void SomeFormControlClickEvent(object sender, ItemChangedEventArgs e)
{
_myService.Add("hi");
}
}
For that simple example creating the MainMasterMenu directly would be no issue, but you would have to pass the reference to your service
MainPage = new MainMasterMenu(unityContainer.Resolve<IMyService>());
But this would mean that you'll have to change that line every time the constructor of MainMasterMenu changes. You could circumvent this by registering the MainMasterMenu, too.
unityContainer.RegisterType<MainMasterMenu>();
...
MainPage = unityContainer.Resolve<MainMasterPage>();
Anyway, anytime you want to navigate to another page, which needs any dependency registered with unity, you'll have to make sure to resolve its dependencies properly, which requires (at least indirect) access to the unity container. You could pass a wrapper that encapsules the access to unity
interface IPageResolver
{
T ResolvePage<T>()
where T : Page;
}
and then implement that resolver with unity
public class UnityPageResolver
{
private IUnityContainer unityContainer;
public UnityPageResolver(IUnityContainer unityContainer)
{
this.unityContainer = unityContainer;
}
public T ResolvePage<T>()
where T : Page // do we need this restriction here?
{
return unityContainer.Resolve<T>();
}
}
This gets registered with unity
unityContainer.RegisterInstance<IUnityContainer>(this);
unityContainer.RegisterType<IPageResolver, UnityPageResolver>();
But you should have a look at the Prism library (see here) that solves many of the issues (e.g. it provides an INavigationService that lets you navigate to other pages without caring about the dependencies and it provides facilities to resolve viewmodels automatically, including dependencies).
I’m using Service Stack, and I can´t (or I don´t know how make a Service class with constructor).
Here is what I did:
public class AppHost : AppSelfHostBase
{
public AppHost()
: base("ClientService", typeof(ClientService).Assembly)
{
}
public override void Configure(Container container)
{
}
}
public class Context : ApplicationContext
{
//This class is invoked from program.cs (winform application)
//Here i have the logic of what form should i start.
var listeningOn = string.Format("http://*:{0}/", port);
var appHost = new AppHost();
appHost.Init();
appHost.Start(listeningOn);
ClientService cl = new ClientService((ILayout)f, i);
}
public class ClientService : Service
{
private readonly ILayout _activeForm;
private static Init _initConf;
public ClientService(ILayout f, Init i)
{
_activeForm = f;
_activeForm.GetClientData(i);
_initConf = i;
}
public HttpResult Post(Person request)
{
//Here i use _activeForm and _initConf
}
}
So, as I said, in the class ClientService, I wanna make a constructor, but when I make a request to the post message, it shows me the following error:
Error trying to resolve Service
'DexBrokerClient.Services.ClientService' or one of its auto wired
dependencies
ServiceStack Services are autowired and created using both Constructor and Property Injection. Any Constructor parameters are mandatory and must be registered in ServiceStack's IOC in AppHost.Configure(), e.g:
public override void Configure(Container container)
{
container.Register<ILayout>(c => ...);
container.Register<Init>(c => ...);
}
Whereas any public properties on Services are optional and will be populated from the IOC if they exist or are otherwise null.
Resolving Services
Services should be resolved using base.ResolveService<T> API's when inside Service class or HostContext.ResolveService<T>() singleton outside of Services. This resolves the Service class from ServiceStack's IOC and is populated with the IRequest context (if any).
#Mati, #TheMiddleMan The #mythz's answer expects you to have some general knowledge about dependency injection and containers that is IOC (inversion of control). In your question you ask about constructor injection. ServiceStack's IOC can handle it using auto-wiring if you have pre-configured (registered) the parameter object, for example:
container.Register(c => new Layout());
For more samples see https://docs.servicestack.net/ioc.
More about IOC and DI (dependency injection) can be read from https://dzone.com/articles/ioc-vs-di.
I am experimenting with a throwaway vNext application. What I'm trying to do is create a dummy class called 'DataService' which will return some data, and then create objects which use DI to take an IDataService parameter as the constructor.
So my IDataService/DataService definitions are:
public interface IDataService
{
DateTime Created { get; }
}
public class DataService : IDataService
{
private DateTime created = DateTime.Now;
public DateTime Created
{
get { return created; }
}
}
In my startup class I register this as a singleton:
public void Configure(IApplicationBuilder app)
{
app.UseServices(services =>
{
services.AddSingleton<Data.IDataService, Data.DataService>();
});
And in a class I created, I add the IDataService interface as a constructor dependency:
internal class Constraint : IRouteConstraint
{
private readonly IDataService _dataService;
public Constraint (IDataService dataService)
{
_dataService = dataService;
}
public bool Match(....)
{
//call dataservice for match
}
}
The class here with the constructor dependency is an IRouteConstraint which I'm trying to use to get dynamic routes in MVC - the final part of the startup class code is this:
app.UseMvc(routes => {
routes.MapRoute(name: "TestRoute", template: "{*constraints}", defaults: new { controller = "Test", action = "Index" }, constraints: new { constraint = new Constraint() }); //<--- how to construct using DI?
});
The issue is that the Constraint() class can't be created because it is missing the constructor. All the examples show a Controller using DI and the instantiation of the Controller classes are handled by MVC so that is part of the 'automagic' we don't see at first glance.
So my question is:
How do I instantiate the 'Constraint' object so that DI provides the implementation of the DataService singleton?
Is my issue because I'm trying this in the Configure method in the UseMvc method, or is my problem more fundamental than that?
I figure I'm missing some way of getting DI to act as an object factory to provide my objects instead of trying to declaratively creating them.
If you're wanting to resolve your Constraint through the Dependency Injection, you'll need to register it, first:
services.AddTransient<Constraint>();
Once you have the IApplicationBuilder, you can access the services directly:
app.ApplicationServices.GetRequiredService<Constraint>();
Of course, if you don't want to add your Constraint type to the services list, you can still access the IDataService the same way.
This assumes you have using Microsoft.Framework.DependencyInjection; declared at the top of your Startup; given your other syntax, I believe that you do.
I read the following article .NET Junkie - Meanwhile... on the command side of my architecture which was suggested by another stackoverflow user that outlines the command pattern and provides a strategy for how to use it with DI at the end of the article.
This has helped immensely but the one thing I'm missing, let's say I create a new class called CheckoutCustomerCommandHandler.
Now, let's say I need to inject this command and the MoveCustomerCommandHandler into a controller for whatever reason via the constructor. How does this affect the DI container setup and the constructor?
At the core, they both implement the same interface. It seems like this would result in a lookup issue for the DI container. In the article example, here is their sample injector setup:
public interface ICommandHandler<TCommand>
{
void Handle(TCommand command);
}
// Exactly the same as before, but now with the interface.
public class MoveCustomerCommandHandler
: ICommandHandler<MoveCustomerCommand>
{
private readonly UnitOfWork db;
public MoveCustomerCommandHandler(UnitOfWork db,
[Other dependencies here])
{
this.db = db;
}
public void Handle(MoveCustomerCommand command)
{
// TODO: Logic here
}
}
// Again, same implementation as before, but now we depend
// upon the ICommandHandler abstraction.
public class CustomerController : Controller
{
private ICommandHandler<MoveCustomerCommand> handler;
public CustomerController(
ICommandHandler<MoveCustomerCommand> handler)
{
this.handler = handler;
}
public void MoveCustomer(int customerId,
Address newAddress)
{
var command = new MoveCustomerCommand
{
CustomerId = customerId,
NewAddress = newAddress
};
this.handler.Handle(command);
}
}
using SimpleInjector;
using SimpleInjector.Extensions;
var container = new Container();
// Go look in all assemblies and register all implementations
// of ICommandHandler<T> by their closed interface:
container.RegisterManyForOpenGeneric(
typeof(ICommandHandler<>),
AppDomain.CurrentDomain.GetAssemblies());
// Decorate each returned ICommandHandler<T> object with
// a TransactionCommandHandlerDecorator<T>.
container.RegisterDecorator(typeof(ICommandHandler<>),
typeof(TransactionCommandHandlerDecorator<>));
// Decorate each returned ICommandHandler<T> object with
// a DeadlockRetryCommandHandlerDecorator<T>.
container.RegisterDecorator(typeof(ICommandHandler<>),
typeof(DeadlockRetryCommandHandlerDecorator<>));
Here's what your class declarations would look like...
public class CheckoutCustomerCommandHandler :
ICommandHandler<CheckoutCustomerCommand> {...}
public class MoveCustomerCommandHandler :
ICommandHandler<MoveCustomerCommand> {...}
These may look like they implement the same interface, but they actually compile to two different interfaces because the generics arguments are different. Your DI framework will be able to distinguish between them.
In a WCF service project, I have created a simple wrapper for MEF CompositionContainer to simplify its instantiation :
internal class CompositionProxy
{
private static Lazy<CompositionContainer> m_lazyCC;
static CompositionProxy()
{
m_lazyCC = new Lazy<CompositionContainer>(() =>
{
var batch = new CompositionBatch();
var dc1 = new DirectoryCatalog(
HttpContext.Current.Server.MapPath("~/bin")
);
return new CompositionContainer(dc1);
}
);
}
public static CompositionContainer DefaultContainer
{
get
{
return m_lazyCC.Value;
}
}
}
The idea is to have one CompositionContainer for the application lifetime, which search for export in the bin directory.
Then, I set up some webservices, that requires to have on imported property :
All of them are built like this :
public class MyService: IMyService
{
public MyService()
{
CompositionProxy.DefaultContainer.SatisfyImportsOnce(this);
}
[Import]
private IContext Context { get; set; }
public void DoTheJob()
{
// Logic goes here
}
}
Elsewhere, I have one class that match this export :
[Export(typeof(IContext))]
public class MyContext
{
public MyContext(){
Log("MyContext created");
}
}
In the constructor, I ask the composition container to populate the IContext Context property.
This seems to work, in my service, I can see the Context property is correctly populated.
However, I'm experiencing memory leaks, and my tracing show me the MyContext class is instantiated only once.
Can you clarify if I'm misusing the composition framework ?
I supposed it's a good idea to have one composition container for the application lifetime, was I wrong ?
the multiple calls to SatisfyImportsOnce seems to populate the target with the same unique instance. Is it true ? If true, how can I simply change my code to have a new instance each time the method is called ?
Any suggestion to improve my code ?
I supposed it's a good idea to have one composition container for the application lifetime
Yes, you are supposed to create one container for the application lifetime.
the multiple calls to SatisfyImportsOnce seems to populate the target with the same unique instance. Is it true ? If true, how can I simply change my code to have a new instance each time the method is called ?
You need [Import(RequiredCreationPolicy=CreationPolicy.NonShared)].
Any suggestion to improve my code ?
If possible, do not expose the container as a global and litter your code with calls to it. That's the Service Locator pattern, which has some disadvantages when compared to Dependency Injection. Instead of your service trying to compose itself, just declare what it needs:
[Export(typeof(IMyService))]
public class MyService: IMyService
{
private readonly IContext context;
public MyService(
[Import(typeof(IContext),
RequiredCreationPolicy=CreationPolicy.NonShared)]
IContext context)
{
if (context == null)
throw new ArgumentNullException("context");
this.context = context;
}
public void DoTheJob()
{
// Logic goes here
}
}
In a WCF service, I think you should only need to call the container in your ServiceHostFactory implementation. I'm not really familiar with WCF though.