How tell to Unity.WebApi dependency injection framework, inject the correct class in the correct controller?
DI Project Container
public class UnityContainerConfig
{
private static IUnityContainer _unityContainer = null;
public static IUnityContainer Initialize()
{
if (_unityContainer == null)
{
_unityContainer = new Microsoft.Practices.Unity.UnityContainer()
.RegisterType<IMyInterface, MyClass1>("MyClass1")
.RegisterType<IMyInterface, MyClass2>("MyClass2")
}
}
-MVC PROJECT-
public static class UnityConfig
{
public static void RegisterComponents()
{
GlobalConfiguration.Configuration.DependencyResolver = new UnityDependencyResolver(DependencyInjection.UnityContainer.UnityContainerConfig.Initialize());
}
}
Controller 1:
private IMyInterface _myInterface
///MyClass1
public XController(
IMyInterface myInterface
)
{
_myInterface = myInterface
}
Controller 2:
private IMyInterface _myInterface
///MyClass2
public YController(
IMyInterface myInterface
)
{
_myInterface = myInterface
}
Rather than using a strategy or facade to solve this, a better solution would be to redesign your interfaces to be unique per controller. Once you have a unique interface type, your DI container will automatically inject the right service into each controller.
Option 1
Use a generic interface.
public interface IMyInterface<T>
{
}
public class XController
{
private readonly IMyInterface<XClass> myInterface;
public XController(IMyInterface<XClass> myInterface)
{
this.myInterface = myInterface;
}
}
public class YController
{
private readonly IMyInterface<YClass> myInterface;
public YController(IMyInterface<YClass> myInterface)
{
this.myInterface = myInterface;
}
}
Option 2
Use interface inheritance.
public interface IMyInterface
{
}
public interface IXMyInterface : IMyInterface
{
}
public interface IYMyInterface : IMyInterface
{
}
public class XController
{
private readonly IXMyInterface myInterface;
public XController(IXMyInterface myInterface)
{
this.myInterface = myInterface;
}
}
public class YController
{
private readonly IYMyInterface myInterface;
public YController(IYMyInterface myInterface)
{
this.myInterface = myInterface;
}
}
Related
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;
}
}
I have this class where I'm trying to inject a list of qualifying objects:
public class BlingDispatcher : IBlingDispatcher
{
readonly IEnumerable<IDomainEventHandler> _domainEventHandlers;
#region IBlingDispatcher Members
public BlingDispatcher(IEnumerable<IDomainEventHandler> domainEventHandlers)
{
_domainEventHandlers = domainEventHandlers;
}
}
Classes like this get injected here and work great:
public class NotifyFrontEndSomethingHappened : IDomainEventHandler<SomethingHappened>
{
private readonly IFrontEndNotifier _frontEndNotifier;
public NotifyFrontEndAfterSomethingHappened(IFrontEndNotifier frontEndNotifier)
{
_frontEndNotifier = frontEndNotifier;
}
}
Classes like this do not:
public class NotifyFrontEndAfterEvent : IDomainEventHandler<SomethingHappened>,
IDomainEventHandler<SomethingElseHappened>,
IDomainEventHandler<MoreThingsHappened>,
IDomainEventHandler<AndYetMoreThings>
{
readonly IFrontEndNotifier _frontEndNotifier;
public void Handle(SomethingHappened #event)
{
_frontEndNotifier.Notify(#event, #event.CommanderId);
}
...
}
How can I get classes with multiple interfaces to be injected by autofac as well?
EDIT
More information:
public interface IDomainEventHandler
{
}
public interface IDomainEventHandler<in T> : IBlingHandler<T>, IDomainEventHandler
{
}
public interface IBlingHandler<in T>
{
void Handle(T #event);
}
Registering like this in bootstapper:
container.RegisterAssemblyTypes(AppDomain.CurrentDomain.GetAssemblies())
.Where(x => x.GetInterfaces().Any(i => i.Name.StartsWith("IBlingHandler")))
.AsImplementedInterfaces();
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();
I'm using CQRS pattern in my recent project, so I defined some Commands that I call them CommandParameter and CommandHandlers.
For CommandParameters I have these Classes and Interfaces:
public interface ICommandParameter
{
}
public abstract class BaseEntityCommandParameter<T> : IAggregateRoot,ICommandParameter
where T : ModelEntitySuperType, new()
{
public T Entity { get; set; }
protected BaseEntityCommandParameter()
{
Entity = new T();
}
}
public class InsertCommandParameter<T> : BaseEntityCommandParameter<T>
where T : class, new()
{
}
And for CommandHandlers I defined these Classes and Interfaces:
public interface ICommandHandler<TCommandParameter>
where TCommandParameter :ICommandParameter
{
void Handle(TCommandParameter parameter);
string CommandCode { get; }
}
public class InsertCommandHandler<TCommandParameter, TEntity>
: ICommandHandler<TCommandParameter>
where TCommandParameter : BaseEntityCommandParameter<TEntity>, new()
where TEntity : ModelEntitySuperType, IAggregateRoot, new()
and I used them to make appropriate CommandParameters and CommandHandlers for each Entity for example for Order I have:
public class OrderInsertCommandParameter:InsertCommandParameter<Order>
{
}
public class OrderInsertCommandHandler
: InsertCommandHandler<OrderInsertCommandParameter, Order>
{
private readonly IUnitOfWorkFactory _factory;
public OrderInsertCommandHandler(IUnitOfWorkFactory factory,
IRepository<Order> repository)
: base(repository)
{
_factory = factory;
}
public override void Handle(OrderInsertCommandParameter parameter)
{
var uow = _factory.Create();
parameter.Entity.OrderCreationTime = DateTime.Now;
base.Handle(parameter);
uow.Commit();
}
}
I want to register these CommandParameters and appropriate CommandHandlers using structuremap automatically, How could I define a custom Conversion to do this?
The following should do the trick:
container.Configure(r =>
{
r.Scan(s =>
{
s.Assembly(typeof(ICommandHandler<>).Assembly);
s.ConnectImplementationsToTypesClosing(typeof(ICommandHandler<>));
});
});
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);
}
}