Constructor Inject with Ninject 2 - c#

I've used Ninject with MVC3 for automagic inject of constructor arguments. It worked great.
How do you do something similar with non-MVC code.
For example:
public class Ninja
{
private readonly IWeapon _weapon;
public Ninja(IWeapon weapon)
{
_weapon = weapon;
}
public void Strike()
{
_weapon.Strike();
}
}
public class MyProgram
{
public void DoStuff()
{
var Ninja = new Ninja(); // I'm wanting Ninject to call the parameterized Ninja constructor
ninja.Strike();
}
}
How would I alter the code to get it to work?

public interface IWeapon
{
void Strike();
}
public class Sword : IWeapon
{
public void Strike()
{
Console.WriteLine("black ninja strike");
}
}
public class Ninja
{
private readonly IWeapon _weapon;
public Ninja(IWeapon weapon)
{
_weapon = weapon;
}
public void Strike()
{
_weapon.Strike();
}
}
public class WarriorModule : NinjectModule
{
public override void Load()
{
Bind<IWeapon>().To<Sword>();
}
}
class Program
{
static void Main()
{
var kernel = new StandardKernel(new WarriorModule());
var ninja = kernel.Get<Ninja>();
ninja.Strike();
}
}

Wouldn't it just be:
var ninja = Kernel.Get<Ninja>();
You obviously have to resolve the dependency though Ninject.

You need to have an instance of StandardKernel let's call it kernel and then use kernel.Get<Ninja>(). This works since Ninja is non abstract, so it is considered bound to itself. Obviously some concrete types needs to be bound to IWeapon to allow NInject to create Ninja.

Related

Dependency Injection with factory method .net

I have a structure like below. I need ideas on how to clearly record all instances. Do you think Microsoft.Extensions.DependencyInjection library is suitable for these?
public interface IRules
{
void Do();
}
Implementation :
public class MyRules:IRules
{
public void Do()
{
//Something;
}
}
Businnes Interface:
public interface IRulesOperation
{
void Do();
}
Businnes class:
public class RulesOperation:IRulesOperation
{
private readonly IRules rules;
private readonly IConfiguration conf;
public RulesOperation(IRules rules,IConfiguration conf)
{
this.conf=conf;
this.rules = rules;
}
public void Do()
{
rules.Do();
}
}
Main Class:
public class App
{
IRulesOperation rules;
public App(IRulesOperation rules)
{
this.rules=rules;
}
}

Casting to a base class using generics

I seem to have some trouble understanding generics in c#.
Basically i have a base class called ConfigWorker and a bunch of sub classes which should all use their own config class deriving from BaseConfig.
The ConfigWorker class i want to use should be determined dynamically during runtime given the name of the class as a parameter.
I can instantiate the sub class given it's name, but no matter what i try, i can't get the casting to a sensible base class to work.
Here's my code:
namespace DocumentHandler
{
public class BaseConfig
{
}
public class ConfigWorker<T> where T : BaseConfig
{
public virtual void Work(T options)
{
}
}
public class Worker1 : ConfigWorker<Worker1.Config>
{
public class Config : BaseConfig
{
public string test = "";
}
public override void Work(Config options)
{
//do something
}
}
public class Worker2 : ConfigWorker<Worker2.Config>
{
public class Config : BaseConfig
{
public string test = "";
}
public override void Work(Config options)
{
//do something else
}
}
public class Test
{
public static BaseConfig config;
public static void test()
{
(Activator
.CreateInstance(Type.GetType("DocumentHandler.Worker2"))
as ConfigWorker<BaseConfig>)
.Work(config);
}
}
}
The crucial line is
(Activator
.CreateInstance(Type.GetType("DocumentHandler.Worker2"))
as ConfigWorker<BaseConfig>)
.Work(config);
The casting to ConfigWorker<BaseConfig> returns null, as the cast can not be performed.
Trying to simply cast to ConfigWorker does not compile as the type parameter is missing.
Anything else i can try? CreateInstance obviously just returns an object and i need to cast that to be able to call the Work method
Any help is appreciated.
An instance of Worker2 is not a ConfigWorker<BaseConfig>! It's a ConfigWorker<Worker2.Config>. These are two totally different types. Generic classes are invariant. Only interfaces and delegates can be co- or contra-variant.
In your example, ConfigWorker is even contra-variant in T, meaning you use T as the type of an input parameter to a method. So what you try is actually dangerous.
Imagine your line would work: you get an variable of type ConfigWorker<BaseConfig>, so you could rely on this instance having a method Work() which takes a BaseConfig (or something derived from it) as argument. So nothing could stop you from calling it like
worker.Work(new Worker1.Config());
Compiles fine. But wait a moment! Didn't your line state that worker is a Worker2? Worker2 instances can only handle Worker2.Config arguments!
You completely loose type safety this way (well, you would if it was allowed).
There is a flaw in your class design.
This looks like a good problem that factory pattern has good good solution for.
Here is a simplified solution
namespace DocumentHandler
{
public interface IBaseConfig
{
}
public class ConfiManager : IBaseConfig
{
}
public abstract class WorkerFactory
{
private readonly IBaseConfig _config;
protected WorkerFactory(IBaseConfig config)
{
this._config = config;
}
public virtual void Work()
{
}
}
public class Worker1 : WorkerFactory
{
private readonly IBaseConfig _config;
public Worker1(IBaseConfig config):base(config)
{
_config = config;
}
public string test = "";
public override void Work()
{
//do something
}
}
public class Worker2 : WorkerFactory
{
private readonly IBaseConfig _config;
public string test = "";
public Worker2(IBaseConfig config):base(config)
{
this._config = config;
}
public override void Work()
{
Console.WriteLine("Hello world");
}
}
public class Test
{
public static IBaseConfig config = new ConfiManager();
public static void test()
{
WorkerFactory worker =
(Worker2) Activator.CreateInstance(Type.GetType("DocumentHandler.Worker2"), config);
worker.Work();
}
}
}

Autofac constructor chaining

How would I implement the equivalent using Autofac to output 123.
I've had a look at the following but I don't think it quite fits in with what I'm trying to achieve.
http://docs.autofac.org/en/latest/advanced/adapters-decorators.html
Maybe someone can enlighten me - is this decorator?
using System;
namespace Prototypes.Decorator
{
public class Program
{
static void Main()
{
new Class1(new Class2(new Class3(null))).Do();
Console.ReadKey(true);
}
}
public interface ICommand
{
void Do();
}
public abstract class BaseClass : ICommand
{
private readonly ICommand _command;
protected BaseClass(ICommand command)
{
_command = command;
}
public abstract void Do();
public void CallNext()
{
if (_command != null)
{
_command.Do();
}
}
}
public class Class1 : BaseClass
{
public Class1(ICommand command) : base(command)
{
}
public override void Do()
{
Console.Write(1);
CallNext();
}
}
public class Class2 : BaseClass
{
public Class2(ICommand command) : base(command)
{
}
public override void Do()
{
Console.Write(2);
CallNext();
}
}
public class Class3 : BaseClass
{
public Class3(ICommand command) : base(command)
{
}
public override void Do()
{
Console.Write(3);
CallNext();
}
}
}
For bonus points what if there was another interface on the base constructor. Something plausible like protected BaseClass(ICommand command, ILog log) { ... }
There are several ways to build your container in order to achieve what you need, you can use keyed services or lambdas.
Lambdas tend to be a bit less error prone than using strings , so here is a simple container registration that does what you need:
ContainerBuilder cbLambdas = new ContainerBuilder();
cbLambdas.Register<Class3>(ctx => new Class3(null));
cbLambdas.Register<Class2>(ctx => new Class2(ctx.Resolve<Class3>()));
cbLambdas.Register<Class1>(ctx => new Class1(ctx.Resolve<Class2>()));
IContainer containerLambda = cbLambdas.Build();
containerLambda.Resolve<Class1>().Do();
In case of adding ILog interface, as per the following declaration:
public interface ILog
{
void Log();
}
public class NullLog : ILog
{
public void Log() { }
}
And adding it as dependency (in that case only for Class2)
public class Class1 : BaseClass
{
private readonly ILog logger;
public Class1(ICommand command, ILog logger)
: base(command)
{
this.logger = logger;
}
public override void Do()
{
Console.Write(1);
CallNext();
}
}
Then you registration becomes:
ContainerBuilder cbWithLog = new ContainerBuilder();
cbWithLog.RegisterType<NullLog>().As<ILog>();
cbWithLog.Register<Class3>(ctx => new Class3(null));
cbWithLog.Register<Class2>(ctx => new Class2(ctx.Resolve<Class3>()));
cbWithLog.Register<Class1>(ctx => new Class1(ctx.Resolve<Class2>(), ctx.Resolve<ILog>()));
IContainer containerLog = cbWithLog.Build();
containerLog.Resolve<Class1>().Do();

Ninject Binding Issue

I have a wcf service application and I have just implemented ninject library. In ninject web site there is following example:
public class Samurai {
public IWeapon Weapon { get; private set; }
public Samurai(IWeapon weapon)
{
this.Weapon = weapon;
}
}
public class WarriorModule : NinjectModule
{
public override void Load()
{
this.Bind<IWeapon>().To<Sword>();
}
}
I have classes like this. But problem is how can I create instance of Samurai class? It's constructor have parameter (IWeapon), but the parameter is binded Sword or different class. When I want to create instance of Samurai class, compiler expects IWeapon type parameter. In my module class (like WarriorModule) I have already defined it's binding. How can I pass parameter (or some different way) to Samurai class's constuctor?
Try this
class Program
{
static void Main(string[] args)
{
IKernel kernel = new StandardKernel(new WarriorModule());
var samurai = kernel.Get<ISamurai>();
}
}
public interface ISamurai
{
}
public class Samurai : ISamurai
{
public IWeapon Weapon { get; private set; }
public Samurai(IWeapon weapon)
{
this.Weapon = weapon;
}
}
public interface IWeapon
{
}
public class Sword : IWeapon
{
}
public class WarriorModule : NinjectModule
{
public override void Load()
{
this.Bind<ISamurai>().To<Samurai>();
this.Bind<IWeapon>().To<Sword>();
}
}
I just figured out how to do is. There is no need to create ISamurai interface. In Warriormodule:
public class WarriorModule : NinjectModule
{
public override void Load()
{
Bind<IWeapon>().To<Sword>();
Bind<Samurai>().ToSelf();
}
}
To create Samurai instance:
var samurai = kernel.Get<Samurai>();

Generic decorator with Windsor

I'm trying to figure out how to register the following decorator scenario with Castle Windsor. I have the following interface:
public interface ICalculate<T> where T : class
{
void Calculate(T value);
}
And a couple of implementations where the last one is a decorator.
public class FooCalculator : ICalculate<Foo>
{
public void Calculate(Foo value)
{
// do something here with the value..
}
}
public class BarCalculator : ICalculate<Bar>
{
public void Calculate(Bar value)
{
// do something else here....
}
}
public class CalculatorDecorator<T> : ICalculate<T> where T : class
{
private readonly ICalculate<T> _calculator;
public CalculatorDecorator(ICalculate<T> calculator)
{
_calculator = calculator;
}
public void Calculate(T value)
{
// do for example some logging...
_calculator.Calculate(value);
}
}
This is my registration code
container.Register(Classes.FromAssembly()
.BasedOn(typeof(ICalculate<>))
.WithService.Base());
When i request one of the implementations by their generic interface I want Windsor to resolve the CalculatorDecorator with the requested implementation injected in the constructor.
// I would like calculator to be CalculatorDecorator<Foo> in
// this case but it is FooCalculator.
var calculator = container.Resolve<ICalculate<Foo>>();
// The same goes for this one...
var calculator = containr.Resolve<ICalculate<Bar>>();
Thanks in advance!
Edit:
It works if I do like this
container.Register(Component.For<ICalculate<Foo>>()
.ImplementedBy<CalculatorDecorator<Foo>>(),
Component.For<ICalculate<Foo>>()
.ImplementedBy<FooCalculator>());
container.Register(Component.For<ICalculate<Bar>>()
.ImplementedBy<CalculatorDecorator<Bar>>(),
Component.For<ICalculate<Bar>>()
.ImplementedBy<BarCalculator>());
But I would prefer to register all components if it's possible.
container.Register(AllTypes.FromAssembly()
.BasedOn(typeof(ICalculate<>))
.WithService.Base());
Did you try this? We had a similar situation and this worked for us.
UPDATE
I don't think this is possible because you'll create a circular dependency.
I did get it working like following:
Registration
var container = new WindsorContainer();
container.Register(Component.For(typeof(IDecorator<>)).ImplementedBy(typeof(CalculatorDecorator<>)));
container.Register(AllTypes.FromThisAssembly()
.BasedOn(typeof (ICalculate<>))
.WithService.Base());
var fc = container.Resolve<IDecorator<Foo>>();
var bc = container.Resolve<IDecorator<Bar>>();
Interfaces:
public interface ICalculate<T> where T : class
{
void Calculate(T value);
}
public interface IDecorator<T> : ICalculate<T> where T : class
{
}
Implementation:
public class FooCalculator : ICalculate<Foo>
{
public void Calculate(Foo value)
{
// do something here with the value..
}
}
public class BarCalculator : ICalculate<Bar>
{
public void Calculate(Bar value)
{
// do something else here....
}
}
public class CalculatorDecorator<T>: IDecorator<T> where T : class
{
private readonly ICalculate<T> _calculator;
public CalculatorDecorator(ICalculate<T> calculator)
{
_calculator = calculator;
}
public void Calculate(T value)
{
// do for example some logging...
_calculator.Calculate(value);
}
}

Categories