I have an algorithm to run, like this:
public interface IAlgorithm
{
void Run();
}
It depends on the IContainer interface that looks like this:
public interface IContainer
{
int Size();
}
The implemention of this interface needs some data gotten from UI
public class Container : IContainer
{
private readonly List<int> _data;
public Container(IEnumerable<int> data)
{
_data = new List<int>(data);
}
public int Size()
{
return _data.Count;
}
}
Then the implementation of IAlgorithm might look like this:
public class Algorithm : IAlgorithm
{
private readonly IContainer _container;
public Algorithm(IContainer container)
{
_container = container;
}
public void Run()
{
Console.WriteLine(_container.Size());
}
}
I want to implement this interface so that it's injectible via NInject (so I can use it as a constructor parameter for a ViewModel).
public interface IAlgorithmFactory
{
IAlgorithm Create(IEnumerable<int> data);
}
The problem is: I need to be able to get the right instance of IContainer from the Kernel during the Algorithm construction. In the real-world situations the dependency graph of the algorithm is quite big and there is not one thing that needs to be created from the data, but 3 and these things are further dependencies of some other things.
My solution is that all classes that needs to be created from the data have the method called Initialize. The caller must initilize these serives before using other methods. That sounds like a bad practice.
In fact, the real code that I'm talking about can be seen here. Right now everything is injected as Singleton.
Is there some other way to inject those things via NInject?
Note: I already asked this question here, from a design point of view. I think this is the better place to get the answer specifically about an NInject solution.
Just by using Ninject configuration, you can do it in this way:
var kernel = new StandardKernel();
kernel.Bind<IContainer>()
.To<Container>()
.WithConstructorArgument("data",
ctx => ctx.Request.ParentContext.Parameters
.Single(x => x.Name == "data")
.GetValue(ctx, null));
kernel.Bind<IAlgorithm>().To<Algorithm>();
kernel.Bind<IAlgorithmFactory>().ToFactory();
var factory = kernel.Get<IAlgorithmFactory>();
var algorithm = factory.Create(new List<int>() { 1 });
Here the data parmeter is taken from the factory method parameter and passed down to the Container constructor.
Related
If I want to have a service which creates multiple objects which have injectable dependencies how do I code that?
public class MyCreator : ICreator
{
private readonly IAdapter _adapter;
public MyCreator()
{
_adapter = adapter;
}
public List<MappedObjects> Map()
{
List<MappedObjects> mo = new List<MappedObjects>();
foreach (ObjectToMap otm in ObjectToMap)
{
mo.Add(new MappedObject(otm, InjectedDependency dep));
}
}
}
If I register MyCreator with DI, will it know how to provide InjectedDependency?
EDIT: InjectedDependency is not one instance which should be passed to each MappedObject. I want a new instance of InjectedDependency for each new MappedObject.
Perhaps that means I have to create some kind of Factory object which know's how to create instances of InjectedDependency. I cannot provide more code because I don't know how to articulate what I need in C#.
I'm using teh inbuilt DI with .NET Core 2.2.
You will indeed need a factory:
public class MyCreator : ICreator
{
private readonly IInjectedDependencyFactory _factory;
public MyCreator(IInjectedDependencyFactory factory)
{
_factory = factory;
}
public List<MappedObjects> Map()
{
return ObjectToMap.Select(otm => new MappedObject(otm, _factory.Create())).ToList();
}
}
Obviously, you will have to write the factory class and interface and register them with your DI container.
You could also inject the DI container itself, IServiceProvider to get your new services directly from the container, given that that already is a factory. However, many people might consider this a code smell and the Service Locator pattern (that's what it would be) is not held in high regard nowadays. Other people might consider it wasteful to implement a factory on top of a factory. I guess there is no right way, you will have to live with some people calling it wrong, no matter what you do.
To keep your code testable, you need to inject the implementation of InjectedDependency in your MyCreator constructor.
Was unsure how to make a sensible title for this post.
Say I have a class
[Export(typeof(IMessageSender))]
public class MessageSender : IMessageSender
{
private IMessagingInterface _messagingInterface;
private IEventAggregator _eventAggregator;
[ImportingConstructor]
public MessageSender(IMessagingInterface messagingInterface, IEventAggregator eventAggregator)
{
_messagingInterface = messagingInterface;
_eventAggregator = eventAggregator;
}
public void SendMessage(string message)
{
_messagingInterface.Write(message);
}
public InterfaceStatus GetStatus()
{
return _messagingInterface.Status;
}
...
etc. Many methods in this class.
}
and I have several different IMessagingInterface, such as
[Export(typeof(IMessagingInterface))]
public SerialPortInterface : IMessagingInterface
{
..
}
[Export(typeof(IMessagingInterface))]
public UdpInterface : IMessagingInterface
{
..
}
etc
In my application, I currently instantiate the different parts like this at the startup of my application:
eventAggregator = new EventAggregator();
batch.AddExportedValue<IMessageSender>("SerialPortSender", new MessageSender(new SerialPortInterface(), eventAggregator);
batch.AddExportedValue<IMessageSender>("UdpSender", new MessageSender(new UdpInterface (), eventAggregator);
...
etc for the rest
Then I can specify which one I want injected elsewhere by using the contract name.
However, I feel like doing this composition myself in the bootstrapper and creating instances with new is wrong and unnecessary, but I haven't found a way to do it differently.
Have a look at this post:
Getting all types that implement an interface
And then use Activator.CreateInstance(...) to construct the instances (see: https://msdn.microsoft.com/en-us/library/system.activator.createinstance.aspx)
Something like this should do it:
eventAggregator = new EventAggregator();
var type = typeof(IMyInterface);
var types = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes())
.Where(p => type.IsAssignableFrom(p));
foreach (var t in types)
{
var instance = (IMyInteface)Activator.CreateInstance(t);
batch.AddExportedValue<IMessageSender>(t.Name, new MessageSender(instance, eventAggregator);
}
As Tchi Yuan pointed out, using a IOC framework is also an option such as:
Unity
Ninject
These will handle the scanning of assemblies and instance creation for you according to the configurations you provide.
I've had this problem in the past and what I did is that I used Microsoft Unity in conjuncture with MEF and then simply pass your unity container to your MEF extension/plugin constructor. Registering and resolving named dependencies with Unity is trivial.
I have a service that I want to be able to create according to the Inversion of Control principle so I have created an interface and a service class.
public interface IMyService
{
void DoSomeThing1();
void DoSomeThing2();
void DoSomeThing3();
string GetSomething();
}
public class MyService : IMyService
{
int _initialValue;
//...
public MyService(int initialValue)
{
_initialValue = initialValue;
}
public void DoSomeThing1()
{
//Do something with _initialValue
//...
}
public void DoSomeThing2()
{
//Do something with _initialValue
//...
}
public void DoSomeThing3()
{
//Do something with _initialValue
//...
}
public string GetSomething()
{
//Get something with _initialValue
//...
}
}
With for example Unity I can set up my IoC.
public static class MyServiceIoc
{
public static readonly IUnityContainer Container;
static ServiceIoc()
{
IUnityContainer container = new UnityContainer();
container.RegisterType<IMyService, MyService>();
Container = container;
}
}
The problem is the constructor parameter. I could use a ParameterOverride like
var service = MyServiceIoc.Container.Resolve<IMyService>(new ParameterOverrides
{
{"initialValue", 42}
});
But I don't want to use losely typed parameters. What if someone changes the constructor parameter name or adds one parameter? He won't be warned at comple-time and maybe no one will detect it but the end user. Maybe the programmer changes he IoC setup for the tests, but forgets it for the "release" usage, then not even a codebase with 100% code coverage will detect the run-time error.
One could add an Init-function to the interface and service, but then the user of the service have to understand that and remember to call the init function every time he gets an instance of the service. The service becomes less self explanetory and open for incorrect usage. I'ts best if methods are not dependent on which order they are called.
One way to make it a little safer would be to have a Create-function on the Ioc.
public static class MyServiceIoc
{
//...
public IMyService CreateService(int initialValue)
{
var service = Container.Resolve<IMyService>();
service.Init(initialValue);
}
}
But the concerns mentioned above still applies if you only look at the service and its interface.
Does anyone have an robust solution to this problem? How can I pass an initial value to my service in a safe way still using IoC?
A DI Container is reflection-based, and fundamentally weakly typed. The problem is much broader than with Primitive Dependencies - it's present everywhere.
As soon as you do something like the following, you've already lost compile-time safety:
IUnityContainer container = new UnityContainer();
container.RegisterType<IMyService, MyService>();
var service = container.Resolve<IMyService>(new ParameterOverrides
{
{"initialValue", 42}
});
The problem is that you can remove the second statement, and the code still compiles, but now it'll no longer work:
IUnityContainer container = new UnityContainer();
var service = container.Resolve<IMyService>(new ParameterOverrides
{
{"initialValue", 42}
});
Notice that the lack of compile-time safety has nothing to do with the Concrete Dependency, but with the fact that a DI Container is involved.
This isn't a Unity problem either; it applies to all DI Containers.
There are cases where a DI Container may make sense, but in most cases, Pure DI is a simpler and safer alternative:
IMyService service = new MyService(42);
Here, you'll get a compiler error if someone else changes the API while you're looking away. That's good: compiler errors give you more immediate feedback than run-time errors.
As an aside, when you pass in a Primitive Dependency and invisibly turn it into a Concrete Dependency, you make it more difficult for the client to understand what's going on.
I'd recommend designing it like this instead:
public class MyService : IMyService
{
AnotherClass _anotherObject;
// ...
public MyService(AnotherClass anotherObject)
{
_anotherObject = anotherObject;
}
// ...
}
This is still easy and type-safe to compose with Pure DI:
IMyService service = new MyService(new AnotherClass(42));
How can I pass an initial value to my service in a safe way still using IoC?
You can explicitly call a type's constructor while registering it in Unity using the IUnityContainer.RegisterInstance method:
container.RegisterInstance<IMyService>(new MyService(42));
This would give you the compile-time safety that you mention, but the cost is that it would be instantiated only once, and would be created immediately (as opposed to when it is first requested).
You could perhaps deal with this drawback by using one of the method overloads, which accepts a LifetimeManager class.
It depends on your use case, but in IoC container world it could look something like this:
public class MyService : IMyService
{
int _initialValue;
// ...
public MyService(IConfigurationService configurationService)
{
_initialValue = configurationService.GetInitialValueForMyService();
}
// ...
}
If your class with constructor parameters is outside your code (e.g. in 3rd party library), you can use an adapter.
public class AdaptedMyService : MyService
{
public AdaptedMyService(IConfigurationService configurationService)
: base(configurationService.GetInitialValueForMyService())
{
}
}
And then register adapted class in IoC container like this:
container.Register<IMyService, AdaptedMyService>();
I know this question might look like it's a duplicate but please let me explain.
So I created several components that use a pluggable architecture, basically I can freely add new implementations and they will be injected and processed automatically for me. This is really handy in several scenarios.
I'm going to talk about the simplest one, validating components.
One of the reasons to use a design like this is that I like to expose my roles explicitly as explained by Udi Dahan
Basically I have code like this:
public interface IValidatorRuner
{
void Run<TTarget>(TTarget target);
}
public class ValidatorRunenr : IValidatorRuner
{
private readonly IServiceLocator _serviceLocator;
public ValidatorRunenr(IServiceLocator serviceLocator)
{
_serviceLocator = serviceLocator;
}
public void Run<TTarget>(TTarget target)
{
// this is the dynamic/pluggable phase
// is this an antipattern???
var foundValdiators = _serviceLocator.GetAllInstances<IValidator<TTarget>>();
foreach (var valdiator in foundValdiators)
{
valdiator.IsSatisfiedBy(target);
}
}
}
This code lets me expose my validation rules explicitly like this:
//this will allow me to create validators in this way
//and they will be automatically injected and resolved for me
//(easy, to read, easy to write, easy to test, pff I could even smoke this validator easily)
public class OneValdiationRuleExplicitlyExposedAndEasyToTest : IValidator<Person>
{
public bool IsSatisfiedBy(Person target)
{
return target.Age > 18;
}
}
public class Person
{
public int Age { get; set; }
}
public interface IValidator<TTarget>
{
bool IsSatisfiedBy(TTarget target);
}
And I will use this code like this:
//usage
public class SomeCommandHandler
{
private readonly IValidatorRuner _validatorRuner;
public SomeCommandHandler(IValidatorRuner validatorRuner)
{
_validatorRuner = validatorRuner;
}
public void SomeMethod()
{
_validatorRuner.Run(new Person{Age = 16});
}
}
Validation was just one example, I also use it to fire domain events and to run pipelines and filters in the same pluggable way
Is using the service locator in this way an anti-pattern?
I know I might be hiding some dependencies, but the thing is that the dependencies are dynamically injected and discovered when the application initializes (Composition root)
Your thoughts will be greatly appreciated
In my opinion, the primary issue with your code sample is that the service locator is itself injected into the implementation of ValidatorRunner. For me, this is an anti-pattern, but perhaps not the one you're asking about.
Any answer I might give boils down to the capabilities of your service locator implementation. But for sure it should not be passed into the constructor of your class. Instead, the service locator should itself pass these things in when you ask it for an implementation of "IValidatorRuner"
As an example, you can inject a factory that knows how to load the dynamic validator instances for a given type.
If anyone is interested, I found a way to remove the ServiceLocator in my objects and still dynamically load/discover dependencies at run time.
The way I solved it was by registering my components in my DI container in the following way (using the Mediator pattern):
Binding mediator (shortbus) with/to ninject
var kernel = new StandardKernel();
kernel.Bind(x => x.FromThisAssembly()
.SelectAllClasses()
.InheritedFromAny(
new[]
{
typeof(IValidatorRunner<>)
})
.BindDefaultInterfaces());
And my final implementation looks like:
public interface IValidatorRuner<in TTarget>
{
void Run(TTarget target);
}
public class ValidatorRunenr<TTarget> : IValidatorRuner<TTarget>
{
private readonly IEnumerable<IValidator<TTarget>> _validators;
public ValidatorRunenr(IEnumerable<IValidator<TTarget>> validators)
{
_validators = validators;
}
public void Run(TTarget target)
{
foreach (var valdiator in _validators)
{
valdiator.IsSatisfiedBy(target);
}
}
}
Usage
//usage
public class SomeCommandHandler
{
private readonly IValidatorRuner<OneValdiationRuleExplicitlyExposedAndEasyToTest> _validatorRuner;
public SomeCommandHandler(IValidatorRuner<OneValdiationRuleExplicitlyExposedAndEasyToTest> validatorRuner)
{
_validatorRuner = validatorRuner;
}
public void SomeMethod()
{
_validatorRuner.Run(new Person{Age = 16});
}
}
In few words, by registering an opened generic type, my container resolves any call to that type creating a concrete-closed-generic-type instance at runtime for me.
As you can see in the usage, I do not have to create a specific concrete-closed-generic type of IValidatorRunner<OneValdiationRuleExplicitlyExposedAndEasyToTest> because the container creates one for me.
And there you go, now I'm happy because I removed the service locator from my domain objects =)
I have the following code:
_container = new UnityContainer();
_container.RegisterType<IDownloader, Downloader>();
_container.RegisterType<INewObject, NewObject>();
_container.RegisterType<SearchViewModel>();
SearchViewModel class with constructor injection:
class SearchViewModel
{
private readonly Func<IDownloader> _downloaderFactory;
private readonly INewObject _newObject;
private IDownloader _downloader;
public SearchViewModel(Func<IDownloader> downloaderFactory, INewObject newObject)
{
_downloaderFactory = downloaderFactory;
_newObject = newObject;
}
}
The question: How to register SearchViewModel that has Fun<> as parameter?
_container.RegisterType<SearchViewModel>(new InjectionConstructor(DownloaderFactory()));
The code above works only without INewObject.
The goal: Resolve factory with InjectionConstructor and resolve INewObject, INewObject2, INewObject3 automatically (like without parameters: RegisterType<SearchViewModel>()).
Is it possible? Maybe alternates?
I have solved the problem:
_container.RegisterType<Func<IDownloader>>(new InjectionFactory(i =>
new Func<IDownloader> (() => _container.Resolve<IDownloader>())));
_container.RegisterType<SearchViewModel>();
new Func is a key, because before I tried:
_container.RegisterType<Func<IDownloader>>(new InjectionFactory(i =>
_container.Resolve<IDownloader>()));
Also the better way to use IDownloaderFactory instead of Func<IDownloader> downloaderFactory. IDownloaderFactory can encapsulate the delegate.
Also I think that using a delegate as dependency inside factory is better solution than broken Composition Root.
The generally accepted pattern to use here is to declare an abstract factory and make it slightly more explicit:
public interface IDownloaderFactory
{
IDownloader Create();
}
Then you create a class to represent the factory that simply uses the container again to resolve instances:
public class DownloaderFactory : IDownloaderFactory
{
private UnityContainer _Container;
public DownloaderFactory(UnityContainer container)
{
this._Container = container;
}
public IDownloader Create()
{
return this._Container.Resolve<IDownloader>();
}
}
Using this approach is more explicit and plays more nicely with the containers, also it still keeps the container away from your application and business logic, now you just need a small adjustment to your SearchViewModel class:
class SearchViewModel
{
private readonly IDownloaderFactory _downloaderFactory;
private readonly INewObject _newObject;
public SearchViewModel(IDownloaderFactory downloaderFactory, INewObject newObject)
{
_downloaderFactory = downloaderFactory;
_newObject = newObject;
Console.WriteLine(downloaderFactory.Create().GetHashCode());
Console.WriteLine(downloaderFactory.Create().GetHashCode());
}
}
Now you can see it just works and creates new instances each time.
Setting up the container would look like this:
var container = new UnityContainer();
container.RegisterType<IDownloader, Downloader>();
container.RegisterType<INewObject, NewObject>();
container.RegisterType<IDownloaderFactory, DownloaderFactory>();
container.RegisterType<SearchViewModel>();
container.RegisterInstance(container);
var model = container.Resolve<SearchViewModel>();
Notice that you need to register the instance of the container you are working with so that the factory gets the same instance either using this method or a ThreadLocal instancing or something.
Note:
also just be wary of the fact that using the Func approach or using the container to resolve the downloader may cause undesired effects in your client. For instance if the container is set up by default to be transient to objects of Downloader then a new instance is created each time. Chaning the lifetime on the container may result in the client to get the same instance each time. In such a case it is better to manually construct the downloader object in the factory and use the container only for the arguments of downloader.