Is Service Locator an anti pattern in a pluggable architecture? - c#

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 =)

Related

Service which creates multiple children with dependencies

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.

NInject complex injection with dynamic data

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.

IoC, Dependency injection and constructor arguments

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>();

Circular reference using IoC

I am using windsor castle as my IoC container, and has run in to a bit of a problem.
First of all - i know about: Castle Windsor: How to prevent circular references in factory-created objects were the created objects refers back to the factory
But since circular reference is considered as "Code Smell" and i should consider refactoring app architecture i am asking anyway.
I have very similar situation:
public class OperationsFactory
{
private GeneralSettingsManager m_generalSettings;
private Dictionary<OperationType, OperationCreatorBase> m_creators;
public OperationsFactory(IKernel container)
{
m_generalSettings = container.Resolve<GeneralSettingsManager>();
var creators = container.ResolveAll<OperationCreatorBase>(); //FIRST DEPENDENCY
foreach (var creator in creators)
{
m_creators.Add(creator.CreatorOperationType, creator);
}
}
.
.
.
private OperationCreatorBase GetCreator(OperationType operationType)
{
return m_creators[operationType];
}
}
Now i would like to take in code this OperationFactory from windsor container so i can easily read all the successors of OperationCreatorBase.
now there is a code for OperationCreator:
public class ConvertToFullOperationCreator : OperationCreatorBase
{
private OperationsFactory m_operationsFactory;
private SomeHelper m_someHelper;
public ConvertToFullOperationCreator(IKernel container)
{
m_operationsFactory = container.Resolve<OperationsFactory>(); //SECOND dependency which causes error
m_someHelper = container.Resolve<SomeHelper>();
}
public override OperationType CreatorOperationType
{
get { return OperationType.SomeOperation2; }
}
public override List<OperationBase> CreateOperation(FileData fileData)
{
//HERE I WANT TO USE FACTORY to get creators for SUBOPERATIONS
var creator1 = m_operationsFactory.GetCreator(OperationType.SomeSuboperation1);
creator1.CreateOperation(fileData);
.
.
.
m_someHelper.DoSomething(fileData);
var creator2 = m_operationsFactory.GetCreator(OperationType.SomeSuboperation2);
creator2.CreateOperation(fileData);
.
.
.
}
}
I really want to use windsor castle for both of this classes because i am using more components (such as SomeHelper in creator... and more). In factory class i am using nice method ResolveAll provided by IKernel.
There is obvious constructor circular reference but i cant figure out, whats wrong with this component design and most important - how to make this runnable.
I know i can do it with Property Injection on both sides but this kills this nice dependency injection feature, so thats why the answer said in upper stackoverflow question wont solve my problem. Am i missing something?
Is there any suggestion how to redesign those two components or how to Split the "C" class said in nice article about circular reference here: http://misko.hevery.com/2008/08/01/circular-dependency-in-constructors-and-dependency-injection/
In order to solve cyclic dependency you should inject Func<OperationsFactory> instead of OperationsFactory via constructor (or resolve using IKernel/ IWindsorContainer).
public class ConvertToFullOperationCreator : OperationCreatorBase
{
private Func<OperationsFactory> get_operationsFactory;
private SomeHelper m_someHelper;
public ConvertToFullOperationCreator(
SomeHelper someHelper,
Func<OperationsFactory> get_operationsFactory)
{
this.get_operationsFactory = get_operationsFactory
m_someHelper = someHelper;
}
public override List<OperationBase> CreateOperation(FileData fileData)
{
var m_operationsFactory = get_operationsFactory()
// Here you can place all your code
var creator1 = m_operationsFactory
.GetCreator(OperationType.SomeSuboperation1);
...
var creator2 = m_operationsFactory
.GetCreator(OperationType.SomeSuboperation2);
...
}
}
First OperationsFactory should be registered, then Func<OperationsFactory>.
container.Register(Component.For<Func<OperationsFactory>>()
.UsingFactoryMethod(container =>
{
Func<OperationsFactory> func = container.Resolve<OperationsFactory>;
return func;
}));
I've already answered the similar question Cyclic dependency with Castle Windsor IoC for NHibernate ISession. You can find more details there.
If you already use IoC container it is better to inject instances of concrete types via constructor instead of IKernel. IKernel is a part of your infrastructure.
In order to resolve IEnumerable<T> CollectionResolver can be used.
public class OperationsFactory
{
private GeneralSettingsManager m_generalSettings;
private Dictionary<OperationType, OperationCreatorBase> m_creators;
public OperationsFactory(
GeneralSettingsManager generalSettings,
IEnumerable<OperationCreatorBase> creators)
{
m_generalSettings = generalSettings;
foreach (var creator in creators)
{
m_creators.Add(creator.CreatorOperationType, creator);
}
}
...
}
EDIT :
If you cannot register Func<OperationsFactory> you can create it in the constructor in order to load OperationsFactory lazily.
public class ConvertToFullOperationCreator : OperationCreatorBase
{
private Func<OperationsFactory> get_operationsFactory;
private SomeHelper m_someHelper;
public ConvertToFullOperationCreator(
IKernel container)
{
this.get_operationsFactory = () => container.Resolve<OperationsFactory>;
m_someHelper = container.Resolve<SomeHelper>();
}
public override List<OperationBase> CreateOperation(FileData fileData)
{
var m_operationsFactory = get_operationsFactory()
// Here you can place all your code
var creator1 = m_operationsFactory
.GetCreator(OperationType.SomeSuboperation1);
...
var creator2 = m_operationsFactory
.GetCreator(OperationType.SomeSuboperation2);
...
}
}

Implementing DI in a particular situation

I'm trying to implement DI in a class, but I'm not sure that my design is appropriate.
The relevent code in the class I want to add DI to
class DoerValidation
{
public DoerValidation()
{
compileData();
}
private void compileData()
{
doersActive = Doer.GetActiveDoers();
//...
}
}
And in my Doer class
public partial class Doer
{
private static readonly DoerRepository repository = new DoerRepository();
public static IEnumerable<Doer> GetActiveDoers()
{
return repository.Doers.Where(c => c.Person.IsActive);
}
}
I just don't get how I could implement DI in this situation. Maybe the GetActiveDoers method is bad design? Where would you put this method otherwise?
Would it be a good practice to start adding new methods directly in the repository? Some people told me it should stay clean so it implements only this
public interface IDoerRepository
{
IQueryable<Doer> Doers { get; }
void SaveDoer(Doer doer);
void DeleteDoer(Doer doer);
}
It sounds like you need to inject the DoerRepository into DoerValidation basically - pass it into the constructor.
Both the GetActiveDoers and the static variable go against the principles of DI, IMO.
Static methods and properties are procedural in nature. If you expose your GetActiveDoers() method statically, there is no way to inject its functionality -- clients can only ignore it or use it inline wherever it's needed.
If you're committed to DI and to a static implementation, you need to write an instance wrapper for that static class and inject the instance wrapper.

Categories