here's my situation:
I have an application that generates stuff based on templates (using T4) and i have multiple templates class that inherit from an ITemplate interface.
What i wanna do in my Main is to dinamically inject some ITemplate implementations in my Generator class, what implementation to use being read from a, let's say, configuration file. Then in the Main i should call the Generator that will understand what template to use and call the proper TransformText().
I'm using Ninject.
It's the first time i use Dependency Injection in a statically typed language, so I'm not sure on how to proceed...
Regards,
Hugo
If you are truly want to use DI here a simple example, but if you are searching something like plugin system you might wanna check out mef.
Lets assume you have a generator
public class Generator
{
private ITemplate _template;
public Generator(ITemplate t)
{
_template = t;
}
public void Generate()
{
_template.Generate();
}
}
Setup your Modules.
public class MyNinjectModules : NinjectModule
{
public override void Load()
{
Bind<ITemplate>().To< TemplateImplementation>();
Bind<Generator>().ToSelf();
}
}
then prepare your Ninject Kernel, and use it.
public class Program
{
public static void Main(
{
var kernel = new StandardKernel(MyNinjectModules);
var myGenerator = kernel.Get<Generator>();
}
}
Related
I understand this is only possible with a workaround. But why?
I want to add plugin support to my app. So I designed an abstract class that all future plugins will need to implement. Every plugin must implement a GetVersion() method like in this example code:
public abstract class Plugin
{
public abstract int GetVersion();
}
public class MyPlugin : Plugin
{
public override int GetVersion()
{
return 1;
}
}
This of course works perfectly as long as I instantiate the plugin before calling the GetVersion() method.
But if I want to get the version number of the plugin before creating an instance of it? To check compatibility for example?
public class Program
{
public Program()
{
if (MyPlugin.GetVersion() > 1)
{
PluginLoader.Load(new MyPlugin());
}
}
}
Although it might not answer directly your question "WHY" I think below solution might be usefull in your scenario:
Use assembly version attribute:
Assembly thisAssem = typeof(MyPlugin).Assembly;
AssemblyName thisAssemName = thisAssem.GetName();
Version ver = thisAssemName.Version;
It never can be done by C# because a static method cannot be implemented in derived classes.
Like the workaround, you can create a static factory to create the instance.
public abstract class Plugin
{
public abstract int GetVersion();
}
public class FactoryPlugin<T> where T : Plugin, new()
{
public static int GetVersion()
{
return new T().GetVersion();
}
}
public class Program
{
public Program()
{
if (FactoryPlugin<MyPlugin>.GetVersion() > 1)
{
}
}
}
Consider using the Factory pattern in a way similar to what a COM class factory does. You create two classes, your useful class, and a class factory class. Your class factory class implements IPluginFactory. You package it with your Plugin. The plugin factory has vary simple methods, but one of them allows your Plugin to be created. It's close to what #ThierryV showed, but without static methods. So the process is:
Use whatever you are planning to use to store and instantiate your plugins, but instead of instantiating a plugin, you instantiate the appropriate Plugin Factory
You can have the Plugin factory do what ever you want -- get detailed information about the plugin, allow instantiation of the latest version or a particular version of the plugin - go to town
But, eventually, you use an instance of the factory to instantiate your Plugin.
This is a good place to start: What exactly is a Class Factory?, but Don Box's Essential COM book is where I learned all this stuff, a long time ago in a place far away.
Does ninject works for static property bindings?
I set IEventHandlerFactory with Ninject,
public class ServiceModule: NinjectModule
{
public override void Load()
{
Kernel.Bind<IEventHandlerFactory>().To<EventHandlerFactoryService>();
}
}
And my static class
public static class DomainEvents
{
public static IEventHandlerFactory EventHandlerFactory { get; set; }
public static void Raise<T>(T domainEvent)
{
EventHandlerFactory
.GetDomainEventHandlersFor(event)
.ForEach(h => h.Handle(event));
}
}
But this does not bind to static property.
DomainEvents.EventHandlerFactory is Null
Is there any way to bind property?
Since ninject doesn't have a concept of dividing "creating all bindings" and "using the kernel", there's of course no extension point for "tell me when the kernel is done with all bindings so i can do something".
With a static class it also doesn't make sense to request it from the kernel.
So the obvious answer is: no.
Of course, the obvious solution is just to extend your code where you're done building up the kernel (probably close to where you do var kernel = new StandardKernel()) with a call like
DomainEvents.EventHandlerFactory = kernel.Get<IEventHandlerFactory>();
Alternative 1 - tying initialization to activation of another type
If that initialization should be tied to the activation of another type, let's say IFoo, you can also do:
kernel.Bind<IFoo>()
.To<Foo>()
.InSingletonScope()
.OnActivation(x =>
DomainEvents.EventHandlerFactory = kernel.Get<IEventHandlerFactory>());
Alternative 2 - tying initialization to loading of a NinjectModule
You can sublcass NinjectModule and in it's Load you can initialize the static property. This works in case you can make sure the module is only loaded after the kernel is sufficiently initialized to create an IEventHandlerFactory.
Disclaimer
Both alternatives probably suck because their not clear and not straight forward. They hide a dependency deep in some place. I'd only use one of these if the first approach is not feasible, for example because your writing a plugin and there's no extension point post-kernel initialization.
Do you really need DomainEvents class to be static?
Maybe you can do as follows. Raise will still be static though.
You will have to call kernel.Get though.
public class DomainEvents
{
public static IEventHandlerFactory EventHandlerFactory { get; set; }
public DomainEvents(IEventHandlerFactory factory)
{
EventHandlerFactory = factory;
}
public static void Raise<T>(T domainEvent)
{
EventHandlerFactory
.GetDomainEventHandlersFor(event)
.ForEach(h => h.Handle(event));
}
}
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 =)
C#. I have a base class called FileProcessor:
class FileProcessor {
public Path {get {return m_sPath;}}
public FileProcessor(string path)
{
m_sPath = path;
}
public virtual Process() {}
protected string m_sath;
}
Now I'd like to create to other classes ExcelProcessor & PDFProcessor:
class Excelprocessor: FileProcessor
{
public void ProcessFile()
{
//do different stuff from PDFProcessor
}
}
Same for PDFProcessor, a file is Excel if Path ends with ".xlsx" and pdf if it ends with ".pdf". I could have a ProcessingManager class:
class ProcessingManager
{
public void AddProcessJob(string path)
{
m_list.Add(Path;)
}
public ProcessingManager()
{
m_list = new BlockingQueue();
m_thread = new Thread(ThreadFunc);
m_thread.Start(this);
}
public static void ThreadFunc(var param) //this is a thread func
{
ProcessingManager _this = (ProcessingManager )var;
while(some_condition) {
string fPath= _this.m_list.Dequeue();
if(fPath.EndsWith(".pdf")) {
new PDFProcessor().Process();
}
if(fPath.EndsWith(".xlsx")) {
new ExcelProcessor().Process();
}
}
}
protected BlockingQueue m_list;
protected Thread m_thread;
}
I am trying to make this as modular as possible, let's suppose for example that I would like to add a ".doc" processing, I'd have to do a check inside the manager and implement another DOCProcessor.
How could I do this without the modification of ProcessingManager? and I really don't know if my manager is ok enough, please tell me all your suggestions on this.
I'm not really aware of your problem but I'll try to give it a shot.
You could be using the Factory pattern.
class FileProcessorFactory {
public FileProcessor getFileProcessor(string extension){
switch (extension){
case ".pdf":
return new PdfFileProcessor();
case ".xls":
return new ExcelFileProcessor();
}
}
}
class IFileProcessor{
public Object processFile(Stream inputFile);
}
class PdfFileProcessor : IFileProcessor {
public Object processFile(Stream inputFile){
// do things with your inputFile
}
}
class ExcelFileProcessor : IFileProcessor {
public Object processFile(Stream inputFile){
// do things with your inputFile
}
}
This should make sure you are using the FileProcessorFactory to get the correct processor, and the IFileProcessor will make sure you're not implementing different things for each processor.
and implement another DOCProcessor
Just add a new case to the FileProcessorFactory, and a new class which implements the interface IFileProcessor called DocFileProcessor.
You could decorate your processors with custom attributes like this:
[FileProcessorExtension(".doc")]
public class DocProcessor()
{
}
Then your processing manager could find the processor whose FileProcessorExtension property matches your extension, and instantiate it reflexively.
I agree with Highmastdon, his factory is a good solution. The core idea is not to have any FileProcessor implementation reference in your ProcessingManager anymore, only a reference to IFileProcessor interface, thus ProcessingManager does not know which type of file it deals with, it just knows it is an IFileProcessor which implements processFile(Stream inputFile).
In the long run, you'll just have to write new FileProcessor implementations, and voila. ProcessingManager does not change over time.
Use one more method called CanHandle for example:
abstract class FileProcessor
{
public FileProcessor()
{
}
public abstract Process(string path);
public abstract bool CanHandle(string path);
}
With excel file, you can implement CanHandle as below:
class Excelprocessor: FileProcessor
{
public override void Process(string path)
{
}
public override bool CanHandle(string path)
{
return path.EndsWith(".xlsx");
}
}
In ProcessingManager, you need a list of processor which you can add in runtime by method RegisterProcessor:
class ProcessingManager
{
private List<FileProcessor> _processors;
public void RegisterProcessor(FileProcessor processor)
{
_processors.Add(processor)
}
....
So LINQ can be used in here to find appropriate processor:
while(some_condition)
{
string fPath= _this.m_list.Dequeue();
var proccessor = _processors.SingleOrDefault(p => p.CanHandle(fPath));
if (proccessor != null)
proccessor.Process(proccessor);
}
If you want to add more processor, just define and add it into ProcessingManager by using
RegisterProcessor method. You also don't change any code from other classes even FileProcessorFactory like #Highmastdon's answer.
You could use the Factory pattern (a good choice)
In Factory pattern there is the possibility not to change the existing code (Follow SOLID Principle).
In future if a new Doc file support is to be added, you could use the concept of Dictionaries. (instead of modifying the switch statement)
//Some Abstract Code to get you started (Its 2 am... not a good time to give a working code)
1. Define a new dictionary with {FileType, IFileProcessor)
2. Add to the dictionary the available classes.
3. Tomorrow if you come across a new requirement simply do this.
Dictionary.Add(FileType.Docx, new DocFileProcessor());
4. Tryparse an enum for a userinput value.
5. Get the enum instance and then get that object that does your work!
Otherwise an option: It is better to go with MEF (Managed Extensibility Framework!)
That way, you dynamically discover the classes.
For example if the support for .doc needs to be implemented you could use something like below:
Export[typeof(IFileProcessor)]
class DocFileProcessor : IFileProcessor
{
DocFileProcessor(FileType type);
/// Implement the functionality if Document type is .docx in processFile() here
}
Advantages of this method:
Your DocFileProcessor class is identified automatically since it implements IFileProcessor
Application is always Extensible. (You do an importOnce of all parts, get the matching parts and Execute.. Its that simple!)
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.