In my implementation, I need to dynamically resolve a service, based on the servicekey. Therefor, I want to pass a Func, but can't get that working. Any help on this is appreciated.
Let's have the following implemention:
public interface IMyInterface {
void Foo();
}
public class ClassA : IMyInterface {
void Foo() => BarA();
}
public class ClassB : IMyInterface {
void Foo() => BarB();
}
public class ClassC : IOtherInterface {
private readonly Func<string, IMyInterface> getInstance_;
void ClassC(Func<string, IMyInterface> getInstance)
{
getInstance_ = getInstance;
}
void SomeLogic()
{
IMyInterface implementation = getInstance("keyA");
implementation.Foo();
}
}
public static void Main()
{
var c = new Container();
c.Register<IMyInterface, ClassA>(serviceKey:"keyA");
c.Register<IMyInterface, ClassB>(serviceKey:"keyB");
c.Register<IOtherInterface, ClassC>();
c.Resolve<IOtherInterface>();
}
The last call fails, which I understand. The exception thrown is:
DryIoc.ContainerException: 'Unable to resolve IMyInterface with passed arguments [_String0] IsWrappedInFunc, IsDirectlyWrappedInFunc
in wrapper Func<String, IMyInterface> FactoryId=10 with passed arguments [_String0] IsResolutionCall
from Container with Scope {no name}
with Rules with {TrackingDisposableTransients} and without {ThrowOnRegisteringDisposableTransient}
with normal and dynamic registrations:
("keyA", {FactoryID=32, ImplType=ClassA}) ("keyB", {FactoryID=33, ImplType=ClassB}) '
I figured out how to register this with a Delegate:
c.RegisterDelegate<Func<string, IMyInterface>>(r => (key) => c.Resolve<IMyInterface>(key));
But in the documentation, DryIoc recommends using factory-methods above Delegates.
I've played a lot with Made.Of-notations (which I find poorly documented), but have not found a working one.
Is this possible with a (static) Factory-method?
If you need to dynamically select the service based on the key but without relying on Service Locator anti-pattern (without injecting the IResolver into ClassC) -
you may inject all available service factories as described here https://github.com/dadhi/DryIoc/blob/master/docs/DryIoc.Docs/RegisterResolve.md#keyed-registrations in the second example:
public class ClassC : IOtherInterface {
private readonly Func<string, IMyInterface> _implementations;
void ClassC(KeyValuePair<string, Func<IMyInterface>>[] implementations)
{
_implementations = implementations;
}
void SomeLogic()
{
var implementationFactory = _implementations.First(x => x.Key == "keyA").Value;
var implementation = implementationFactory();
implementation.Foo();
}
}
BTW, The same approach is taken in Autofac and maybe by other DI containers capable to compose the wrappers like Func, Lazy and the collections.
BTW2, If you don't like the KeyValuePair you may use Tuple instead.
Related
Trying to do this with Ninject's factory extensions.
void Main()
{
IKernel kernel = new StandardKernel();
kernel.Bind<C>().ToMethod(ctx => new C());
kernel.Bind<IBFactory>().ToFactory();
var a = kernel.Get<A>();
a.Do();
}
public class A
{
IBFactory _fact;
public A(IBFactory factory)
{
_fact = factory;
}
public void Do()
{
_fact.Get("blah").Dump();
}
}
public class B
{
public B(C c, string s)
{
}
}
public interface IBFactory
{
B Get(string s);
}
public class C
{
}
The factory interface fails because it does not have a C to throw into the B() constructor. However it knows how to make a C from the kernel, but looking it up is beyond the scope of the default factory method implementation.
I can make a custom IInstanceProvider and pass that into the factory method e.g ToFactory(() => new myCustomIIProvider()) which resolves the C from the kernel, but it seems like a lot of work.
Is there an easier way to get Ninject to self resolve the missing ctor arg ?
Actually, the problem isn't the binding for the C service, but the binding for B.
The default Factory instance provider will create named bindings for methods starting with Get (see here).
Either change your factory method to something other than Get or add this to create an empty named binding for B:
kernel.Bind<B>().ToSelf().Named("");
Lets assume these classes/interfaces:
public interface ICommand
{
}
public class SomeCommand : ICommand
{
}
public interface ICommandHandler<T> where T : ICommand
{
void Handle(T arg);
}
public class SomeCommandHandler : ICommandHandler<SomeCommand>
{
void Handle(SomeCommand arg){ /* do something */ }
}
public interface ICommandBus
{
void RegisterHandler<T>(T t) where T : ICommandHandler<T>;
void RegisterHandlerByParam<T2>(ICommandHandler<T2> t2) where T2 : ICommand;
void RegisterHandlerMethod<T3>(Action<T3> action) where T3 : ICommand
}
public class TheCommandBus : ICommandBus
{
// implements ICommandBus ...
}
I want to register all implementations of ICommandHandler<> automatically.
All variants (Register*) are valid solutions even though I would prefer Action parameter while it is more flexible and has no dependency to Handler interface (just action delegate).
Autofac has the capability to register types based upon assembly scanning and register the found implementations of a generic interface, for example:
builder.RegisterAssemblyTypes(Assembly.LoadFrom("MyAssembly.dll"))
.AsClosedTypesOf(typeof(ICommandHandler<>));
So I have all implementations registered. Now I need to Register them all automatically to TheCommandBus. How to do that?
I can do this manually by adding those lines (e.g. during OnActivated):
builder.RegisterType<TheCommandBus>().As<ICommandBus>().OnActivated(args =>
{
// now I need to list all implementations here!!! please, no...
args.Instance.RegisterHandler<ICommandHandler<SomeCommand>>(args.Context.Resolve<ICommandHandler<SomeCommand>>());
// does not look better to me than before ...
args.Instance.RegisterHandlerByParam<SomeCommand>(args.Context.Resolve<ICommandHandler<SomeCommand>>())
// uses delegate for, but still need to list all variants
args.Instance.RegisterHandlerMethod<SomeCommand>(args.Context.Resolve<ICommandHandler<SomeCommand>>().Handle)
});
If I want to use such a type in a lambda expression during registration I have the problem, that I need to identify the concrete type, like for this example on activation process for another component. But I don't want to list all of them manually... want something like this automatically.
How do I catch all ICommandHandler implementations AND have them automatically registered with the Register* method?
Edit:
Another variant is to extend the SomeCommandHandler class to register itself when resolved inside its constructor:
public SomeCommandHandler(ICommandBus commandBus)
{
// and register here, for example
commandBus.RegisterHandlerbyParam(this);
}
This way I have to provide AutoActivate() to the AsClosedTypesOf registration result. (a possible solution, but now the "handlers" have two responsibilities... registration and handling)
This is an interesting and tricky problem. The generics definitely add to that complexity since going non-generic would be a simple IEnumerable<T> resolution.
But... I think I can help.
You'll take advantage of...
The OnRegistered event in RegisterAssemblyTypes so you can look at what was actually registered.
The OnActivating event for the bus so you can do the registration of the handlers.
Closures to carry the list of registered handler types into the OnActivating event.
Some fancy-schmancy reflection to create the closed generic version(s) of the RegisterHandler method on the bus.
Here's a full, working example showing how to do it. Note I had to change the ICommandBus interface for RegisterHandler a bit since it wouldn't compile for me in the originally listed form, but you should be able to adapt as needed. I ran this in ScriptCs to verify.
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Autofac;
public interface ICommand { }
public class CommandOne : ICommand { }
public class CommandTwo : ICommand { }
public interface ICommandHandler<T> where T : ICommand
{
void Handle(T arg);
}
public class CommandOneHandler : ICommandHandler<CommandOne>
{
public void Handle(CommandOne arg) { }
}
public class CommandTwoHandler : ICommandHandler<CommandTwo>
{
public void Handle(CommandTwo arg) { }
}
public interface ICommandBus
{
IEnumerable<object> Handlers { get; }
void RegisterHandler<TCommand, THandler>(THandler handler)
where THandler : ICommandHandler<TCommand>
where TCommand : ICommand;
}
public class CommandBus : ICommandBus
{
private readonly List<object> _handlers = new List<object>();
public IEnumerable<object> Handlers
{
get
{
return this._handlers;
}
}
public void RegisterHandler<TCommand, THandler>(THandler handler)
where THandler : ICommandHandler<TCommand>
where TCommand : ICommand
{
this._handlers.Add(handler);
}
}
var builder = new ContainerBuilder();
// Track the list of registered command types.
var registeredHandlerTypes = new List<Type>();
builder.RegisterAssemblyTypes(Assembly.GetExecutingAssembly())
.AsClosedTypesOf(typeof(ICommandHandler<>))
.OnRegistered(e => registeredHandlerTypes.Add(e.ComponentRegistration.Activator.LimitType));
// Initialize the bus by registering handlers on activating.
builder.RegisterType<CommandBus>()
.As<ICommandBus>()
.OnActivating(e => {
foreach(var handlerType in registeredHandlerTypes)
{
// Due to the generic method, some crazy reflection happens.
// First, get ICommandHandler<T> interface.
var handlerInterfaceType = handlerType.GetInterface("ICommandHandler`1");
// Grab the <T> from the ICommandHandler<T>.
var commandType = handlerInterfaceType.GetGenericArguments()[0];
// Build the closed generic version of RegisterHandler<TCommand, THandler>.
var registerMethod = typeof(ICommandBus).GetMethod("RegisterHandler").MakeGenericMethod(commandType, handlerType);
// Call the closed generic RegisterHandler<TCommand, THandler> to register the handler.
registerMethod.Invoke(e.Instance, new object[] { e.Context.Resolve(handlerInterfaceType) });
}
})
.SingleInstance();
var container = builder.Build();
using(var scope = container.BeginLifetimeScope())
{
var bus = scope.Resolve<ICommandBus>();
foreach(var t in bus.Handlers)
{
// List the handler types registered.
Console.WriteLine(t.GetType());
}
}
I am new at using Autofac, so apologies if this is a stupid question.
Let's say I have an abstract class FooBase with parameterless constructor, and an implementation thereof called Foo.
In my AP.Net MVC5 client code, I would like to be able to create an instance of an object of type FooBase (I have set up Autofac to resolve it to Foo). The lifetime and scope of this instance is limited to my method, and I would like to do it in a fashion similar to calling a factory method if possible.
Currently I am making use of the DependencyResolver, but it seems a bit contrived. Is there a simpler way to do this?
For example, here is what it currently looks like...
public void SendMessage()
{
var foo = DependencyResolver.Current.GetService<FooBase>();
Debug.WriteLine(foo.Name);
}
I am looking for something a little more like this...
public void SendMessage()
{
var foo = IoC.Resolve<FooBase>();
Debug.WriteLine(foo.Name);
}
I think you can use delegate factories
First declare the delegate factory in the type that you want to build at runtime:
public class TestService
{
public delegate TestService Factory();
//other methods....
}
Then you can inject the factory as any other dependency, ex:
public class ExampleController
{
private TestService.Factory _factory;
public ExampleController(TestService.Factory factory)
{
_factory = factory;
}
public OtherMethod()
{
var serviceInstance = _factory();
}
}
Hope this helps!
Instead of using the Service Locator which is an anti-pattern, you can simply inject a factory which allows you to create an instance of the dependency if/when you want. The simplest way is to inject a Func<FooBase>. Autofac supports this natively. If you just register FooBase, AutoFac knows how to inject Func<FooBase>. Here is an example:
public class TestClass
{
private Func<FooBase> m_FooBaseFactory;
public TestClass(Func<FooBase> factory)
{
m_FooBaseFactory = factory;
}
public void TestMethod()
{
var foo = m_FooBaseFactory();
//consume foo here
}
}
My factory is using method injection because I thought this was the best way to make it so far. Besides, I doubt it is a good thing after having to call on its Create method from within a dependent object.
The only way I might think of whilst continuing to use the parameterized factory Create method, is to inject the dependencies directly in the MainPresenter so that it may provide with the dependencies to the method, and I dislike it. It dislike it because it is not the MainPresenter that depends on the ICustomerManagementView and the ICustomerDetailPresenterFactory, it's its dependency. So I would feel like I'm sabotaging my own code by doing so.
MainPresenter
public class MainPresenter : Presenter<IMainView>, IMainViewUiHandler {
public MainPresenter(IMainView view
, ICustomerManagementPresenterFactory customerManagementFactory)
: base(view) {
this.customerManagementPresenterFactory = customerManagementPresenterFactory;
}
public void ManageCustomers() {
// The following line is causing trouble.
// As you can see per the ICustomerManagementPresenterFactory code sample,
// the Create() method takes two parameters:
// 1. ICustomerManagementView, and
// 2. ICustomerDetailPresenterFactory
// Hence I have to provide the dependencies manually, I guess. Which is
// something to avoid at any cost.
var customerManagementPresenter = customerManagementPresenterFactory.Create();
customerManagementPresenter.ShowView();
}
}
ICustomerManagementPresenterFactory
public interface ICustomerManagementPresenterFactory {
// Here. Though I ask Ninject to inject my dependencies, I need to
// provide values to the parameters when calling the method from within
// the MainPresenter class. The compiler won't let me do otherwise! And
// this makes sense!...
[Inject]
CustomerManagementPresenter Create(ICustomerManagementView view
, ICustomerDetailPresenterFactory factory);
}
IMainView
public interface IMainView : IView, IHasUiHandler<IMainViewUiHandler> {
}
IMainViewUiHandler
public interface IMainViewUiHandler : IUiHandler {
void ManageCustomers();
}
IUiHandler
public interface IUiHandler {
}
IHasUiHandler
public interface IHasUiHandler<H> where H : IUiHandler {
H Handler { set; }
}
MainForm
public partial class MainForm : Form, IMainView {
public MainForm() { InitializeComponent(); }
public IMainViewUiHandler Handler { private get { return handler; } set { setHandler(value); } }
}
CompositionRoot
public class CompositionRoot {
private CompositionRoot() { }
public static IKernel BuildObjectGraph() {
IKernel kernel = new StandardKernel();
BindFactories(kernel);
BindViews(kernel);
}
private static void BindFactories(IKernel kernel) {
kernel.Bind(services => services
.From(AppDomain.CurrentDomain
.GetAssemblies()
.Where(a => !a.FullName.Contains("Tests")))
.SelectAllInterfaces()
.EndingWith("Factory")
.BindToFactory()
);
}
private static void BindViews(IKernel kernel) {
kernel.Bind(services => services
.From(AppDomain.CurrentDomain
.GetAssemblies()
.Where(a => a.FullName.Contains("Windows")
&& !a.FullName.Contains("Tests"))
.SelectAllClasses()
.EndingWith("Form")
.BindSelection((type, baseType) => type
.GetInterfaces()
.Where(iface => iface.Name.EndsWith("View"))
)
);
}
}
So I wonder, is it best to implement the ICustomerManagementPresenterFactory and bind the implementer with it within my CompositionRoot, so that I could provide those dependencies through constructor injection to the Create method which shall no longer take any arguments, or shall I make it otherwise?
What I like of writing a simple interface is that Ninject does it all for me to a factory, and no code is necessary to build an instance of the desired type. Besides, when the constructor of the class to be created uses constructor injection, it seems like it is impossible to have a simple factory interface bound as a factory, and one need to implement the factory interface by hand.
What did I get right/wrong?
As a matter of fact you don't need to pass parameters to the factory Create method at all - except in case they are parameters which need to be passed "down" because they cannot be bound in the composition root (for example an input value). However, passing such parameters to constructors is usually a code smell. Mostly, it's a better idea to pass these parameters to methods instead of constructors (for example: Adder.Add(5,3);, not new Adder(5, 3).ComputeResult();.
Now consider the following example, which works perfectly fine:
public class Dependency1 { }
public interface IDependency2 { }
public class Dependency2 : IDependency2 { }
public interface IBar { }
public class Bar : IBar
{
public Bar(Dependency1 d1, IDependency2 d2) { }
}
public interface IBarFactory
{
IBar Create();
}
var kernel = new StandardKernel();
kernel.Bind<IBarFactory>().ToFactory();
kernel.Bind<IBar>().To<Bar>();
kernel.Bind<Dependency1>().ToSelf();
kernel.Bind<IDependency2>().To<Dependency2>();
var factory = kernel.Get<IBarFactory>();
var bar = factory.Create();
bar.Should().BeOfType<Bar>();
even though Bar takes two constructor arguments, the generated IBarFactory's Create() method does not specify so. No problem, ninject will resolve it automatically.
Now let me give you an example what .ToFactory() actually results in. Consider the factory:
public interface ISomeFactory
{
ISomething Create(string parameter1);
}
Will result in (remark: it's realised by interceptors and not by weaving it, so the example is a simplificiation):
public class SomeFactory : ISomeFactory
{
private readonly IResolutionRoot resolutionRoot;
public SomeFactory(IResolutionRoot resolutionRoot)
{
this.resolutionRoot = resolutionRoot;
}
public ISomething Create(string parameter1)
{
this.resolutionRoot.Get<ISomething>(new ConstructorArgument("parameter1", parameter1);
}
}
The ConstructorArgument tells ninject to pass the value of parameter1 to the ctor-parameter named "parameter".
All other parameters are resolved "as usual". If a constructor parameter cannot be resolved (neither passed as parameter nor bound) ninject will throw an exception stating that the parameter cannot be resolved.
I think I get most things about dependency inversion and using an IoC container, but one thing still does not appear clear to me. How do I use autofac to automate the following factory:
public class WidgetFactory
{
public static IWidget Create(int foo, double bar)
{
return new Widget(foo, bar);
}
}
public class Widget
{
private readonly int foo;
private readonly double bar;
public Widget(int foo, double bar)
{
this.foo = foo;
this.bar = bar;
}
}
elsewhere...
public class FoobarUser
{
public void Method()
{
var widget = WidgetFactory.Create(3, 4.863);
// Do something with my widget
// Possibly add it to a widget collection
}
}
Basically, I need thousands of widgets to be created and I'm not sure of the best way of doing so. How would I create the widget factory using autofac and how would I use that in Method, bearing in mind that Method does not contain a reference to the IContainer?
The way to fix this problem is the following:
Change WidgetFactory to define a delegate for creating widgets:
public class WidgetFactory
{
public delegate IWidget Create(int firstParam, double secondParam);
}
In your autofac module, wire up the factory using the RegisterGeneratedFactory method. This will automatically create your factory for you:
public class TestClassModule : Module
{
protected override void Load(ContainerBuilder builder)
{
base.Load(builder);
builder.RegisterType<Widget>().As<IWidget>();
builder.RegisterGeneratedFactory<WidgetFactory.Create>(new TypedService(typeof(IWidget)));
builder.RegisterType<FoobarUser>();
}
}
Inject the factory into FoobarUser:
public class FoobarUser
{
private readonly WidgetFactory.Create factory;
public FoobarUser(WidgetFactory.Create factory)
{
this.factory = factory;
}
public void Method()
{
var widget = this.factory(3, 4.836);
// Do something with my widget
// Possibly add it to a widget collection
}
}
There are basically two ways to handle parameters:
At registration time - you can provide them in lambda registrations (Register(c => T)) or you can append parameters to reflection-based (RegisterType<T>) registrations.
At resolve time - you can either append parameters to Resolve<T>() calls or you can use delegate factories or Func<T> dependencies to dynamically create a factory method that can be used by your component.
There is robust documentation on all of these options with examples over at the Autofac documentation site:
Parameters at registration time
Parameters at resolve time
You would inject dependencies into your factory with an IoC container using constructor or property injection, not args into a method. If you needed to inject specific values as parameters into your service's constructor, you could set that up during registration similar to the below code.
Here, I'm getting a XML file path from my web.config and passing that value into my repository's constructor:
var builder = new ContainerBuilder();
var xmlFileName = HttpContext.Current.Server.MapPath(
ConfigurationManager.AppSettings["xmlData"]);
builder.Register(c => new XmlAdvertisementRepository(new XmlContext(xmlFileName)))
.AsImplementedInterfaces()
.InstancePerHttpRequest();