I'm building a password generator. I'm trying to apply the Dependency Inversion Principle (DIP) but so far my solution still seems to be coupled with concrete data.
How do I decouple the PasswordGenerator? So I don't have to pass to it
new PasswordRequirementsRepository(new PasswordRequirements{[properties assigned here]})
and I can inject an interface instead which will be used by IoC Container?
How can I pass in the data assigned to PasswordRequirements properties to the PasswordGenerator without creating an instance of PasswordRequirementsRepository?
I'm struggling when passing different sets of password requirements because in PasswordGenerator I have to pass a concrete instance of PasswordRequirementsRepository instead of interface. I guess what I'm trying to achieve is to decouple PasswordGenerator from the concrete set of password requirements.
IPasswordRequirementsRepository.cs
public interface IPasswordRequirementsRepository
{
PasswordRequirements GetPasswordRequirements();
}
PasswordRequirementsRepository.cs
public class PasswordRequirementsRepository : IPasswordRequirementsRepository
{
private readonly PasswordRequirements _requirements;
public PasswordRequirementsRepository(PasswordRequirements requirements)
{
_requirements = requirements;
}
public PasswordRequirements GetPasswordRequirements()
{
return _requirements;
}
}
IPasswordGenerator.cs
public interface IPasswordGenerator
{
string GeneratePassword();
}
PasswordGenerator.cs
public class PasswordGenerator : IPasswordGenerator
{
private readonly IPasswordRequirementsRepository _repository;
public PasswordGenerator(IPasswordRequirementsRepository repository)
{
_repository = repository;
}
public string GeneratePassword()
{
PasswordRequirements requirements = _repository.GetPasswordRequirements();
[password generation logic here]
}
}
PasswordRequirements.cs
public class PasswordRequirements
{
public int MaxLength { get; set; }
public int NoUpper { get; set; }
public int NoLower { get; set; }
public int NoNumeric { get; set; }
public int NoSpecial { get; set; }
}
How do I decouple the PasswordGenerator? So I don't have to pass to it and I can inject an interface instead which will be used by IoC Container?
1st - Derive an interface:
public class IPasswordRequirements
{
int MaxLength { get; }
int NoUpper { get; }
int NoLower { get; }
int NoNumeric { get; }
int NoSpecial { get; }
}
2nd - Inherit from interface:
public class PasswordRequirements : IPasswordRequirements
{
public int MaxLength { get; set; }
public int NoUpper { get; set; }
public int NoLower { get; set; }
public int NoNumeric { get; set; }
public int NoSpecial { get; set; }
}
3rd - Update constructor:
public class PasswordGenerator : IPasswordGenerator
{
public PasswordGenerator(IPasswordRequirements passwordRequirements)
{
}
That's it.
Don't use a repository here
My fear is that your understanding of a repository and DI infer some time of requirement to always be used together. What I believe your lacking is the code that instantiates dependencies. While a repository may at it's core provide that as a bases of it's pattern, it isn't the correct choice here, because of two reasons; first you aren't storing the items in the repository (that is there is no tier virtual or physical abstraction to wrap the repository around) and secondly you aren't providing generic access to a wide variety of types, just a single one.
At it's core the only thing a repository needs to be useful is a configuration/object to pass objects.. to some other tier (SQL, File system, Web API). A repository is not required in all instances to know anything about how objects are created.
Choose a framework that fits your need
Instead, what you need is a framework built at it's core around DI; object creation and disposal, and having an interface/configuration in which to configure the framework so it can be aware of dependencies to assist in the creation of dependent objects. There are three that come to mind AutoFac, Ninject and Unity. In each of these case, you are in some way, required to configure each type and use it's pattern to create objects. In many cases these Frameworks can even be full featured replacements with other Microsoft Frameworks (MVC for example, has it's own way to instantiate objects, but can be replace with other DI Frameworks). In no way are these frameworks required to know configuration on how to pass these objects to other tiers. It may do so simply by configuration as a by-product, but at it's core that's not what is configured.
For example with Autofac, first you create builder which is basically a fancy way to create a configuration:
var builder = new ContainerBuilder()
Then you register your types:
builder.RegisterType<PasswordRequirements>.As<IPasswordRequirements>();
Create a Container which manages objects: from their instantiation to their configuration.
var container = builder.Build();
Create a scope which defines the duration of an objects lifetime.
using (var scope = new BeginLifetimeScope())
{
// all objects created by scope which be disposed when the scope is diposed.
var passwordRequirements = scope.Resolve<IPasswordRequirements>();
}
By default passwordRequirements will be a new PasswordRequirements(). From there you simply build out your necessary dependency requirements and let the framework handle the rest.
Crux of the issue related to Dependency Inversion
On creating the instance of the PasswordGenerator. which inject, IPasswordRequirementsRepository, in current design there's a limitation of passing the concrete instance of PasswordRequirements, which shall be avoided for true Dependency inversion design.
Following are the possible solutions:
Create an interface or preferably an abstract class for the PasswordRequirements, which can be overridden and can be injected on the need basis, which will be automatically injected when IPasswordRequirementsRepository is injected in the PasswordGenerator
Let's consider the abstract class:
public abstract class BasePasswordRequirements
{
public abstract int MaxLength { get; set; }
public abstract int NoUpper { get; set; }
public abstract int NoLower { get; set; }
public abstract int NoNumeric { get; set; }
public abstract int NoSpecial { get; set; }
}
public class PasswordRequirements : BasePasswordRequirements
{
public override int MaxLength { get; set; }
public override int NoUpper { get; set; }
public override int NoLower { get; set; }
public override int NoNumeric { get; set; }
public override int NoSpecial { get; set; }
}
Using Ninject DI container Binding would be as follows, along with named binding:
Kernel.Bind<IPasswordRequirementsRepository>().To<PasswordRequirementsRepository>()
Kernel.Bind<BasePasswordRequirements>().To<PasswordRequirements>()
PasswordRequirementsRepository will be as follows:
public class PasswordRequirementsRepository : IPasswordRequirementsRepository
{
private readonly BasePasswordRequirements Requirements{get;}
public PasswordRequirementsRepository(BasePasswordRequirements requirements)
{
Requirements = requirements;
}
public BasePasswordRequirements GetPasswordRequirements()
{
return Requirements;
}
}
Another option would be constructor Injection, in that case PasswordRequirements, may not need a Base class or interface, in that case binding would be like:
Kernel.Bind<IPasswordRequirementsRepository>().To<PasswordRequirementsRepository>()
.WithConstructorArgument("requirements", new
PasswordRequirements { .... });
This would call the correct constructor, with relevant values filled in
You may also consider combination of both approached 1 and 2 , where you create a base class / interface for PasswordRequirements and also constructor injection.
For various versions of PasswordRequirements, that you may want to inject consider named binding, following shall be example, instead of:
public class PasswordRequirementsRepository : IPasswordRequirementsRepository
{
private readonly Func<string,BasePasswordRequirements> RequirementsFunc{get;}
public PasswordRequirementsRepository(Func<string,BasePasswordRequirements> requirementsFunc)
{
RequirementsFunc = requirementsFunc;
}
public BasePasswordRequirements GetPasswordRequirements(string name="Version1")
{
return requirementsFunc(name);
}
}
Ninject Binding would be as follows
Kernel.Bind<Func<string,BasePasswordRequirements>>()
.ToMethod(context => name => context.Kernel
.Get<BasePasswordRequirements>(name);
);
Bind<BasePasswordRequirements>().To<PasswordRequirements>().Named("Version1");
Bind<BasePasswordRequirements>().To<AnotherPasswordRequirements>().Named("Version2");
Here the Name for Binding can be passed at the run-time to tweak object that will be injected and thus change the behavior by run-time, thus achieving dependency inversion by using a DI framework like Ninject, which lot of flexible options
Based on the code snippet in your question, the implementation of PasswordGenerator is decoupled from the implementation of the IPasswordRequirementsRepository as it is the interface that is given as constructor argument and not a specific implementation.
To decouple the PasswordRequirementsRepository from a specific implementation of the PasswordRequirements you can do one of two things.
Introduce an interface IPasswordRequirements.
Make PasswordRequirements abstract.
Either approach will decouple the implementation of PasswordRequirementsRepository from the implementation of PasswordRequirements.
DI container
How do I decouple the PasswordGenerator? So I don't have to pass to it
new PasswordRequirementsRepository(new PasswordRequirements{[properties assigned here]})
and I can inject an interface instead which will be used by IoC Container? How can I pass in the data assigned to PasswordRequirements properties to the PasswordGenerator without creating an instance of PasswordRequirementsRepository?
I believe that this part of the question builds on a misunderstanding of the role of the DI container. When building your container you will register all the Classes/Interfaces that is needed in your system. This could look something like the following:
Register<IPasswordRequirements>().To<PasswordRequirements>();
Register<IPasswordRequirementsRepository>().To<PasswordRequirementsRepository>();
Register<IPasswordGenerator>().To<PasswordGenerator>();
After registering everything you can ask the container to provide you with an instance of an interface. In your case, this would be an instance of IPasswordGenerator. The request typically looks a something like this:
var passwordGenerator = contain.Resolve<IPasswordGenerator>();
Normally you only request the topmost component of your program, as the DI container knows what is needed to instantiate every class the component depends on. You would not create a new instance of PasswordGenerator by manually resolving the dependencies and the inject these into the constructor. This approach counteracts the purpose of the DI container.
One option might be to use generics to abstract out the different types of password requirements you might use, and pass the options through the GeneratePassword method since that's really a parameter to how you generate the password. I.E.
interface IPasswordGenerator<TPasswordRequirements>
{
string GeneratePassword(TPasswordRequirements reqs);
}
interface IPasswordRequirementRepository<TPasswordRequirements>
{
TPasswordRequirements GetPasswordRequirements();
}
Implemented by
class DefaultPasswordReqs
{
public int MaxLength { get; set; }
// ...
}
class DefaultPasswordGenerator : IPasswordGenerator<DefaultPasswordReqs>
{
public string GeneratePassword(DefaultPasswordReqs reqs)
{
// ... logic specific to DefaultPasswordReqs
}
}
class InMemoryPasswordRequiremntsRepository<TPasswordRequirements> :
IPasswordRequirementRepository<TPasswordRequirements>
{
private readonly TPasswordRequirements _reqs;
public InMemoryPasswordRequiremntsRepository(TPasswordRequirements reqs)
{
_reqs = reqs;
}
public TPasswordRequirements GetPasswordRequirements()
{
return _reqs;
}
}
And then in whatever code depends on the password generator, have it take a dependency which has the specifc type of password requirements it will use and read the requirements and use those requirements to generate the password.
var requirements = _passwordRequiremntsRepository.GetPasswordRequirements();
var password = _passwordGenerator.GeneratePassword(requirements);
Related
So I have this data class:
public class RecentProject
{
public string ProjectName { get; set; }
public string ProjectPath { get; set; }
public DateTime CreationDate { get; set; }
public string OutputFolder { set; get; } = "";
}
It just defines the properties of the recent project, and I wanted to apply dependency inversion so I extracted an interface from the class:
public interface IRecentProject
{
DateTime CreationDate { get; set; }
string OutputFolder { get; set; }
string ProjectName { get; set; }
string ProjectPath { get; set; }
}
then I made an ioc container(inversion of control) and registered the class type as the interface:
Mvx.IoCProvider.RegisterType<IRecentProject, RecentProject>();
so anywhere in my app when I want to create a recent project I just use:
Mvx.IoCProvider.Resolve<IRecentProject>();
but after I did this I ran into some problems that would be hard to solve with the current setup so I thought that maybe this is not the correct way to apply dependency inversion in this class because none of the dependency inversion benefits would apply like:
unit testing: as I will not be unit testing a data class
The ability to change the class implementation: as any changes in the class will require a change in the interface to be able to use the new features added
So what should I do, I have searched a lot on this topic and could not find a clear answer,
please help and thanks in advance.
If RecentProject is a pure data class, that is it contains no logic, then indeed no need either for unit testing or for abstraction. And of course, IoC is out of scope here.
Things look different when logic and polymorphism are involved. You may want, for example, to have two types of projects with each implementing name validation in its own (simplistic) way:
public class RecentCSharpProject : IRecentProject
{
.
.
.
public string ProjectName
{
get => this.projectName;
set
{
if (!value.EndsWith("csproj"))
{
throw (new Exception("This is not a C# project"));
}
this.projectName = value;
}
}
}
public class RecentFSharpProject : IRecentProject
{
.
.
.
public string ProjectName
{
get => this.projectName;
set
{
if (!value.EndsWith("fsproj"))
{
throw (new Exception("This is not an F# project"));
}
this.projectName = value;
}
}
}
You may still choose to skip unit tests, plus IoC still irrelevant (services are to be injected, not data models).
However, you will now be able to instantiate appropriate class while still "speaking" the interface language to the outside world:
public IRecentProject AddProjectToFileMenu(string projectName, bool isFSharp)
{
IRecentProject project = (isFSharp ? new RecentFSharpProject() : new RecentCSharpProject());
project.ProjectName = projectName; // Internally validate extension according to concrete class
// TODO: add project to file-menu
return (project);
}
I have a class named SomeRule that can be serialized in a XML format. The class uses an ISomeService that I would like to be injected via autofac.
[Serializable]
public class SomeRule
{
[XmlAttribute("Attribute1")]
public string Attribute1 {get;set;}
[XmlAttribute("Attribute2")]
public string Attribute2 { get; set; }
private readonly ISomeService m_someService;
private SomeRule() { }
public SomeRule(ISomeService someService)
{
m_someService = someService;
}
public void DoSomething()
{
m_someService.DoStuff(Attribute1);
}
}
public interface ISomeService {
void DoStuff(string param);
}
public class SomeServiceImpl : ISomeService
{
public void DoStuff(string param) => // Do something with the stuff.
}
Now, my program receives an XML string that I would like to deserialize but also, at the same time, have autofac inject the dependency for me.
void Main()
{
string serializedRule =
"<?xml version=\"1.0\" encoding=\"utf-16\"?>" +
"<SomeRule xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" " +
"xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" " +
"Attribute1=\"Huuuuuge\" " +
"Attribute2=\"Cofveve\" />";
XmlSerializer xmlSerializer = new XmlSerializer(typeof(SomeRule));
var stringBuilder = new StringBuilder(serializedRule);
var newRule = xmlSerializer.Deserialize(
new StringReader(stringBuilder.ToString())) as SomeRule;
// ISomeService was not injected yet. Is it possible?
}
I can make this work by calling the autofac container, get the registered implementation of the ISomeService interface and assign it to a public property of the SomeRule instance. I am looking for a better solution, one that would not require the class to have a public property.
Is there a way to automatically inject dependencies with XmlSerializer?
From a DI standpoint, having data-centric objects with constructors that accepts service dependencies is rather problematic, and should be prevented.
When practicing DI, we try to centralize the composition of our object graphs of application components (i.e. the classes that contain behavior and have dependencies of their own) to a centralized place in the application called the Composition Root.
A data-centric object that includes constructor dependencies, however, complicates this practice, since it either forces composition out of the Composition Root, or forces the addition of factory abstractions for the creation of these objects.
Instead, you should use one of following two alternatives:
Separate data and behavior. This means moving SomeRule's DoSomething method to a new class, that takes SomeRule as an argument in its public method(s). The constructor dependency will move to this new class as well.
Remove the constructor dependency of SomeRule and instead inject it into DoSomething using method injection.
Option 1 might look like this:
// SomeRule only contains data. Much simpler
[Serializable]
public class SomeRule
{
[XmlAttribute("Attribute1")]
public string Attribute1 {get;set;}
[XmlAttribute("Attribute2")]
public string Attribute2 { get; set; }
}
// Moved behavior to new class. This class can be injected
// into consumers, as usual.
public class SomeRuleHandler : IRuleHandler<SomeRule>
{
private readonly ISomeService m_service;
// There's now just one constructor left
public SomeRuleHandler(ISomeService service)
{
m_service = service ?? throw new ArgumentNullException("service");
}
public void DoSomething(SomeRule rule)
{
m_service.DoStuff(rule.Attribute1);
}
}
With option 2, the result will be the following:
[Serializable]
public class SomeRule
{
[XmlAttribute("Attribute1")]
public string Attribute1 { get; set; }
[XmlAttribute("Attribute2")]
public string Attribute2 { get; set; }
// No more constructors. The dependency is supplied in the method,
// but *not* stored.
public void DoSomething(ISomeService service)
{
service.DoStuff(Attribute1);
}
}
Before this is marked as duplicate I have looked around to find an answer for my question, but my scenario is a little more specific than other similar questions found on SO and I don't think anwers like "it's a bad practice" apply.
I am working on some design choices for modeling the domain following the DDD approach with Entity Framework, and I am interested in a way to inject dependencies into Entities. To be precise the only dependencies I consider worth injecting are factories for domain objects that belong to the aggregate root I am working with or wrappers around static classes like the one below:
public class CurrentTimeProvider : ITimeProvider
{
public DateTime GetTime()
{
return DateTime.Now();
}
}
The purpose of the wrapper is to make unit testing easier and I am not a fan of the double dispatch pattern for this case as it breaks encapsulation.
Sample entity:
public class ActivationToken
{
protected ITimeProvider TimeProvider;
public ActivationToken(ITimeProvider timeProvider)
{
TimeProvider = timeProvider;
}
public virtual DateTime? ConsumedTime { get; protected set; }
public virtual void Consume()
{
ConsumedTime = TimeProvider.GetTime();
}
}
So my question is how do I get Entity Framework to provide my dependency when creating the instance?
Part of the reason this is difficult is that conceptually, you are mixing up injectibles and newables.
See http://misko.hevery.com/2008/09/30/to-new-or-not-to-new/ for an explanation of the difference.
Entities in DDD fit into the 'newable' category. Application services, domain services, repositories etc. are injectible.
An alternative approach for your example is to use 'method injection' and to pass in ITimeProvider directly into the Consume method:
public class ActivationToken
{
public ActivationToken()
{
}
public virtual DateTime? ConsumedTime { get; protected set; }
public virtual void Consume(ITimeProvider timeProvider)
{
ConsumedTime = timeProvider.GetTime();
}
}
This still allows unit testing with a mock time provider, and ensures that the entities fields are only about the state of the entity. You can obtain an instance of the ITimeProvider by injecting it into the application service/use case that will call the Consume method.
I think the simplest way is to avoid constructor injection and register a global Service Locator that you can access from your no-arg constructor, eg:
public class ActivationToken
{
protected ITimeProvider TimeProvider;
public ActivationToken()
{
TimeProvider = ServiceLocator.Instance.GetService<ITimeProvider>();
}
public virtual DateTime? ConsumedTime { get; protected set; }
public virtual void Consume()
{
ConsumedTime = TimeProvider.GetTime();
}
}
As mentioned in the documentation of Castle.Windsor Framework there should be the possibility to resolve a basic class with properties and resolve dependencies by using property injection. I found no solution and the created solution works only for the basic class/object:
public class Class5
{
public int Id { get; set; }
public string Description { get; set; }
public virtual Class9 Class9 { get; set; }
}
public class Class9
{
public int Id { get; set; }
public string Description { get; set; }
public virtual Class10 Class10 { get; set; }
}
in program:
IWindsorContainer castle = new WindsorContainer();
castle.Register(Castle.MicroKernel.Registration.Component.For(typeof(Class5)));
var obj = castle.Resolve<Class5>();
obj.Description = "Hello Class5"; //works fine
other dependencies are not created:
obj.Class9.Description = "Hello Class9"; // no object instance of Class9 created
Does someone have a solution?
The aim is to create only one basic instance of a class and all other instances will be created automatically. Maybe another IOC Framework is better?
The solution should not contain any interfaces or repositories - only a simple solution for this case for the classes.
I already tried Unity and it works fine with InjectionProperty and [Dependency] - Settings, but with IEnumerables or ICollections it ends up in problems, also all unused objects will be saved in database as null reference by using entity framework(!).
With Castle.Windsor that should also be no problem, but I did not find a solution.
Alternative for Class5 with ICollection:
public class Class5
{
public int Id {get;set;}
public string Description {get;set;}
//public virtual Class9 Class9 {get;set;}
public virtual ICollection<Class9> Class9{get;set;}
}
Windsor cannot create an instance of Class9 because you have not registered it.
As already said here, Castle.Windsor can't create any other class than Class5 because you don't register any other class.
To do this you can do the following:
IWindsorContainer castle = new WindsorContainer();
castle.Register(Component.For<Class5>().LifestyleTransient());
castle.Register(Component.For<Class9>().LifestyleTransient());
Now when you call castle.Resolve<Class5>() you will also get an instance of Class9.
If you have more classes to register, I would recommend you to use an IWindsorInstaller:
public class Bootstrapper
{
public IWindsorContainer BootstrapperContainer()
{
IWindsorContainer castle = new WindsorContainer();
return castle.Install(new Installer());
}
}
public class Installer : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(Component.For<Class5>().LifestyleTransient());
container.Register(Component.For<Class9>().LifestyleTransient());
//and so on
}
}
Also make sure you use the correct Lifestyle. By default Castle.Windsor uses LifestyleSingleton() which may not be the behaviour you want.
For more information about the available lifestyles check the official documentation.
I am writing a storage solution for a workflow hierarchy.
To simplify the picture I have 2 types of objects, a Workflow and a WorkflowStep.
Even though WorkflowStep comes hierarchically under the Workflow, the Workflow does not aggregate WorkflowStep because we view these objects as just data containers.
So this leaves me with the following classes:
public class Workflow : Node {
public string UID;
public string parentID;
}
public class WorkflowStep : Node {
public string UID;
public string parentID;
}
public class WorkflowEngine {
public void Store(Workflow wf) {
}
public void Store(WorkflowStep wfs) {
}
}
The reasoning for not aggregating WorkflowStep inside Workflow (even though logically that fits) is that these objects are purely viewed as data containers and they may be subject to changes later on and we want to keep the storage of these objects decoupled from the objects themselves.
The other alternative of course would be to do something like this:
public class Workflow : Node {
public List<WorkflowStep> steps;
public string UID;
public string parentUID;
public void Store() { }
}
public class WorkflowStep : Node {
public string UID;
public string parentID;
public void Store() { }
}
What are the pros and cons of either approach? Is there any literature that talks about both the designs?
Even though Workflow and WorkflowStep are both data containers but keeping these aside from hierarchical measures doesn't solve your decoupling issue.
It is more logical to keep WorkflowStep on hierarchy of Workflow and to get along with decoupling you must introduce IoC in this case.
The Beauty of IoC is that changing the definitions of WorkflowStep which is a list in Workflow class will be just transparent where you will only be considering to register your types on your IoC container.
Let me put you on an example with Ninject IoC container framework.
Define interfaces and implement your data containers accordingly:
public interface IWorkflow {
string UID { get; set; }
string parentID { get; set; }
IList<IWorkflowStep> Steps { get; set; }
}
public interface IWorkflowStep {
string UID { get; set; }
string parentID { get; set; }
}
public class Workflow : IWorkflow, Node {
public string UID { get; set; };
public string parentID { get; set; };
public IList<IWorkflowStep> Steps { get; set; }
}
public class WorkflowStep : IWorkflowStep, Node {
public string UID { get; set; };
public string parentID { get; set; };
}
And now, the Ninject module be:
public class WorkflowModule : NinjectModule
{
#region Overrides of NinjectModule
public override void Load()
{
Bind<IWorkflow>().To<Workflow>();
Bind<IWorkflowStep>().To<WorkflowStep>();
Bind<IList>().To<List>();
}
#endregion
}
This is the single place where you bind your interfaces with concrete classes. And rest of the world, you just ask for an instance of defined interface.
To resolve your type, you need to create a Ninject Kernel which is an IKernel type and a concrete implementation of StandardKernel by loading your defined module.
Which is something like,
var kernel = new StandardKernel(new WorkflowModule());
Now, all you have to do is resolve your desired interface, like:
IWorkflow workflow = kernel.Get<IWorkflow>();
IWorkflowStep workflowStep = kernel.Get<IWorkflowStep>();
The beauty here is, you don't need to worry about your concrete implementation and which is very tightly coupled within your system. Its just the interface you will be dealing with and rest are the worries of your IoC container implementation.
As you are more worried about the implementation of WorkflowStep to be changed and not coupling with Workflow. I guess, this is where IoC comes to play.
Please be noted that, you can use any IoC container framework like Unity, Spring.NET, StructureMap and etc. I used Ninject because I am comfortable with it.