I am writing a desktop GIS application and it supports MapXtreme, MS Virtual Earth and our Custom Map Engine.Users of application can change the map engine at run-time by selecting from dropdownlist.I have a Factory class to change map engine like this.
public class MapFactory implements IMapFactory
{
public IMapEngine createInstance(MapType type)
{
if(type==MapType.MapXtreme)
return new MapXtremeEngine();
else if(type==MapType.VirtualEarth)
return new VirtualEarth();
//....other code
}
}
Can I use a Dependency Injection Framework to create suitable MapEngine implementation at run-time by type parameter?
Your example is the exact right pattern for conditionally instantiating an object. Anywhere you need to create an instance, accept IMapFactory in the constructor.
The most a DI framework should do is hand out the IMapFactory instance.
Related
I have my normal Entity Framework context, which is like this:
public class LikvidoWebsitesApiContext : IdentityDbContext<ApplicationUser>, ILikvidoWebsitesApiContext
{
// code
}
I have made an interface, which has my DBSets.
In my normal solution, I set it up in Ninject like this:
kernel.Bind<ILikvidoWebsitesApiContext>().To<LikvidoWebsitesApiContext>().InRequestScope();
I use the context in my services by adding the ILikvidoWebsitesApiContext inside the constructor, and then I can use the database.
My question is: how do I set this up in the unit Test?
I have tried to do the following:
kernel.Bind(typeof(ILikvidoWebsitesApiContext))
.To(typeof(Mock<LikvidoWebsitesApiContext>))
.Register(true);
(Using the Moq framework)
However, this gives the:
System.InvalidCastException: 'Unable to cast object of type 'Moq.Mock`1[Likvido.Domain.Services.Data.LikvidoWebsitesApiContext]' to type 'Likvido.Domain.Services.Data.ILikvidoWebsitesApiContext'.'
Which do make sense, but I am very unsure how to fix it?
After a quick look at the Ninject wiki I came across
Providers, Factory Methods and the Activation Context
Where they show how to use a Provider to build up instances.
Following the suggestion in the wiki it was advised to extend Provider<T> which includes strong typing.
public MoqContextProvider : Provider<ILikvidoWebsitesApiContext> {
protected override ILikvidoWebsitesApiContext CreateInstance(IContext context) {
var mock = new Mock<ILikvidoWebsitesApiContext>();
// Set up of mock members
return mock.Object;
}
}
And then it is just a matter of plugging into the container
kernel.Bind<ILikvidoWebsitesApiContext>().ToProvider(new MoqContextProvider());
There was also a suggestion about using Factory Methods
A lighter weight alternative to writing IProvider implementations is to bind a service to a delegate method.
kernal.Bind<ILikvidoWebsitesApiContext>()
.ToMethod(context => {
var mock = new Mock<ILikvidoWebsitesApiContext>();
// Set up of mock members
return mock.Object;
});
The provided Func will be bound to the service type for deferred binding and called later when a new instance of the service (i.e. ILikvidoWebsitesApiContext) is required.
Remember that when using Moq you need to set up the desired behavior of the mocks.
I'm struggling with a particular dependency injection problem and I just can't seem to figure it out. FYI: I'm new to guice, but I have experience with other DI frameworks - that's why I believe this shouldn't be to complicated to achieve.
What am I doing:
I'm working on Lagom multi module project and using Guice as DI.
What I would like to achieve:
Inject multiple named instances of some interface implementation (lets' call it publisher, since it will publishing messages to kafka topic) to my service.
This 'publisher' has injected some Lagom and Akka related services (ServiceLocator, ActorSystem, Materializer, etc..).
Now I would like to have two instances of such publisher and each will publish messages to different topic (So one publisher instance per topic).
How would I achieve that?
I have no problem with one instance or multiple instances for the same topic, but if I want to inject different topic name for each instance I have a problem.
So my publisher implementation constructor looks like that:
#Inject
public PublisherImpl(
#Named("topicName") String topic,
ServiceLocator serviceLocator,
ActorSystem actorSystem,
Materializer materializer,
ApplicationLifecycle applicationLifecycle) {
...
}
If I want to create one instance I would do it like this in my ServiceModule:
public class FeedListenerServiceModule extends AbstractModule implements ServiceGuiceSupport {
#Override
protected void configure() {
bindService(MyService.class, MyServiceImpl.class);
bindConstant().annotatedWith(Names.named("topicName")).to("topicOne");
bind(Publisher.class).annotatedWith(Names.named("publisherOne")).to(PublisherImpl.class);
}
}
How would I bind multiple publishers each for it's own topic?
I was playing around with implementing another private module:
public class PublisherModule extends PrivateModule {
private String publisherName;
private String topicName;
public PublisherModule(String publisherName, String topicName) {
this.publisherName = publisherName;
this.topicName = topicName;
}
#Override
protected void configure() {
bindConstant().annotatedWith(Names.named("topicName")).to(topicName);
bind(Publisher.class).annotatedWith(Names.named(publisherName)).to(PublisherImpl.class);
}
}
but this led me nowhere since you can't get injector in you module configuration method:
Injector injector = Guice.createInjector(this); // This will throw IllegalStateException : Re-entry is not allowed
injector.createChildInjector(
new PublisherModule("publisherOne", "topicOne"),
new PublisherModule("publisherTwo", "topicTwo"));
The only solution which is easy and it works is that I change my PublisherImpl to abstract, add him abstract 'getTopic()' method and add two more implementations with topic override.
But this solution is lame. Adding additional inheritance for code reuse is not exactly the best practice. Also I believe that Guice for sure must support such feature.
Any advises are welcome.
KR, Nejc
Don't create a new Injector within a configure method. Instead, install the new modules you create. No child injectors needed—as in the PrivateModule documentation, "Private modules are implemented using parent injectors", so there's a child injector involved anyway.
install(new PublisherModule("publisherOne", "topicOne"));
install(new PublisherModule("publisherTwo", "topicTwo"));
Your technique of using PrivateModule is the one I'd go with in this situation, particularly given the desire to make the bindings available through binding annotations as you have it, and particularly if the full set of topics is known at runtime. You could even put the call to install in a loop.
However, if you need an arbitrary number of implementations, you may want to create an injectable factory or provider to which you can pass a String set at runtime.
public class PublisherProvider {
// You can inject Provider<T> for all T bindings in Guice, automatically, which
// lets you configure in your Module whether or not instances are shared.
#Inject private final Provider<ServiceLocator> serviceLocatorProvider;
// ...
private final Map<String, Publisher> publisherMap = new HashMap<>();
public Publisher publisherFor(String topicName) {
if (publisherMap.containsKey(topicName)) {
return publisherMap.get(topicName);
} else {
PublisherImpl publisherImpl = new PublisherImpl(
topicName, serviceLocatorProvider.get(), actorSystemProvider.get(),
materializerProvider.get(), applicationLifecycleProvider.get());
publisherMap.put(topicName, publisherImpl);
return publisherImpl;
}
}
}
You'd probably want to make the above thread-safe; in addition, you can avoid the explicit constructor call by using assisted injection (FactoryModuleBuilder) or AutoFactory, which will automatically pass through explicit parameters like topicName while injecting DI providers like ServiceLocator (which hopefully has a specific purpose, because you may not need much service-locating within a DI framework anyway!).
(Side note: Don't forget to expose your annotated binding for your PrivateModule. If you don't find yourself injecting your topicName anywhere else, you might also consider using individual #Provides methods with the assisted injection or AutoFactory approach above, but if you expect each Publisher to need a differing object graph you might choose the PrivateModule approach anyway.)
Guice's approach to dependency injection is that the DI framework complements your instantiation logic, it doesn't replace it. Where it can, it will instantiate things for you, but it doesn't try to be too clever about it. It also doesn't confuse configuration (topic names) with dependency injection - it does one thing, DI, and does that one thing well. So you can't use it to configure things, the way you can with Spring for example.
So if you want to instantiate an object with two different parameters, then you instantiate that object with two different parameters - ie, you invoke new twice. This can be done by using provider methods, which are documented here:
https://github.com/google/guice/wiki/ProvidesMethods
In your case, it might look something like adding the following method to your module:
#Provides
#Named("publisherOne")
#Singleton
Publisher providePublisherOne(ServiceLocator serviceLocator,
ActorSystem actorSystem,
Materializer materializer,
ApplicationLifecycle applicationLifecycle) {
return new PublisherImpl("topicOne", serviceLocator,
actorSystem, materializer, applicationLifecycle);
}
Also, you probably want it to be a singleton if you're adding a lifecycle hook, otherwise you could run into memory leaks each time you add a new hook every time it's instantiated.
The Converter property in the code from the blog post, Silverlight MultiBinding solution for Silverlight 4, is not a dependency property, so I can't bind it with a converter (that for technical reasons must be instantiated as part of Unity injection earlier in the application rather than as a simple static resource as part of a user control).
How can I modify the MultiBinding code to accept a bound converter? I tried to make it a dependency property:
public IMultiValueConverter Converter { get { return (IMultiValueConverter)GetValue(ConverterProperty); } set { SetValue(ConverterProperty, value); } }
public static DependencyProperty ConverterProperty = DependencyProperty.Register("Converter", typeof(IMultiValueConverter), typeof(IMultiValueConverter), null);
but I got
DependencyProperty System.Windows.Data.IMultiValueConverter. Converter cannot be set on an object of type ...Binding.MultiBinding.
If this is not a viable option, how can I bind the ConverterParameter property or get something to simulate bindings of a converter to a MultiBinding?
I solved this using the "simulated bindings" route, though that's not my preference if someone has another answer. What I did instead was not build up the converter via dependency injection, but instead had it use service location to get it's needed dependencies. Generally I prefer dependency injection to service location. The "service location" was a matter of storing the Unity container in the application's global resources; from there it's not difficult to get what I need.
I am building a WPF based application. I am using Unity to inject all the different dependencies in my application (defined in App.xaml.cs).
In my MainApplication window I have a pretty complex look-less custom control derived from Control(is has about ten more control integrated in it).
I would like to inject a VM into this custom control without coupling it to any other object in my application (except App.xaml.cs of course)
Injection to any WPF window in my application works well, but when I try injecting to the custom control I am facing to different situation:
1. In case I am using
container.RegisterInstance(container.Resolve);
The DI creates a dummy instance of MyCustomControl and injects the VM (using [Dependency] attribute). However this specific instance is not used when I use it in my XAML:
in which case it initializes a new MyCustomControl ignoring any dependencies.
In case I am using
container.RegisterType();
The MyCustomControl completely ignores the injection.
I realize I am probably doing something wrong (not just technically) and I am really trying to avoid coupling this control (which will obviously solve the issue).
I don't know if this is the best solution and found your question while looking for other options but, alas, here is the approach I used to at least get up and running.
I created a base UnityControl class that subclasses Control. In the constructor, I use the ServiceLocator to get a reference to the container. Then I call the BuildUp method to resolve any dependencies on the derived control class. Any dependencies are implemented as read/write properties marked with the DependencyAttribute.
Here's what UnityControl looks like:
public abstract class UnityControl : Control
{
protected UnityControl() : base()
{
Container = ServiceLocator.Current.GetInstance<IUnityContainer>();
Container.BuildUp(this.GetType(), this);
}
protected IUnityContainer Container { get; private set; }
}
I am in the process of creating a custom membership provider for an ASP.Net MVC website. The provider is being created as a separate class as part of a bigger library. There is a need for the back-end data store to be flexible as it could be an Xml File or SQL database. My initial thought was to create an interface for the data store and inject this into provider using dependency injection.
The end result is required is that a developer can inherit the data store interface and provide the required methods to update the data, which will then be used by the custom membership providers.
However through my own lack of skill I can't figure out how to inject the class into the membership provider when adding it to the website? What needs to be done to link the data store to the provider? What would be the simplest way to enable this in the website?
If you are configuring the custom membership providers via the <membership> element in the Web.config file, then I can see the issues you will have with dependency injection.
The providers are constructed and managed by the framework, and there is no opportunity for you to intercept that construction to provide additional dependency injection for the IDataStore interface.
If my assumption is correct, then what you can do is override the Initialize() method in your custom provider, and do the dependency injection there. You can have a custom name/value setting in the provider configuration which points to a type that implements IDataStore, which is passed as part of a dictionary to the Initialize() method.
Then, you activate an instance of the data store type and set it on the appropriate property:
public class MyMembershipProvider : MembershipProvider
{
public IDataStore DataStore
{
get;
set;
}
public override Initialize(string name, NameValueCollection config)
{
var dataStoreType = config["dataStoreProvider"];
if (!String.IsNullOrEmpty(dataStoreType))
{
var type = Type.GetType(dataStoreType);
DataStore = (IDataStore) Activator.CreateInstance(type);
}
}
}
Initialize() will be called by the framework after it constructs an instance of your provider, so that is the perfect place to do any additional setup work such as this.
For testing scenarios, you just set the data store property on the provider instance itself, as you will be constructing it directly in your tests.
Isn't this better? I use it with MVC3 and ninject. It's enough to add a property to your custom membership provider class. Remember to add "using System.Web.Mvc;" on top.
public IRepository Repository
{
get
{
return DependencyResolver.Current.GetService<IRepository>();
}
}
The simplest way to do dependency injection that I've seen (and actually the only one I've used so far...) is to have a constructor of your dependent class take the interface as a parameter, and assign it to a private field. If you want, you can also add a "default" constructor, which chains to the first one with a default value.
Simplified, it would look something like this:
public class DependentClass
{
private IDataStore _store;
// Use this constructor when you want strict control of the implementation
public DependentClass(IDataStore store)
{
this._store = store;
}
// Use this constructor when you don't want to create an IDataStore instance
// manually every time you create a DependentClass instance
public DependentClass() : this(new DefaultDataStore()) { }
}
The concept is called "Constructor chaining", and there's a lot of articles on the web on how to do it. I find this tutorial very explanatory of the DI pattern.