I have a library that builds instances of types (all public and non-abstract) it discovers dynamically at runtime (using reflection).
To build those instances I want to use Autofac (though I'm willing to use other frameworks) so that the dependencies are automatically incorporated.
The problem is that Autofac is not creating the instance. If I use scope.Resolve() it throws an exception saying the type wasn't registered (which it can't be since it is discovered dynamically at runtime). If I try to use scope.ResolveOptional() it just returns null.
I've used it with types that have just a default public constructor and types that have dependencies and both fail.
EDIT: Added code. The types returned in the types array are all public types with a default parameterless constructor.
var types = AppDomain.CurrentDomain.GetAssemblies()
.SelectMany(s => s.GetTypes())
.Where(p => typeof(ISomeInterface).IsAssignableFrom(p)
&& !p.IsAbstract
&& p.IsPublic).ToArray();
var instance = (ISomeInterface)_dependencyInjectionScope.Resolve(type);
EDIT 2: Regarding some comments, yes I know that these types are not registered beforehand but that happens because the container is already fully built by the time this code is called. I'm looking if there is a way around it (after all I'm providing Autofac with a type that is both concrete and constructable)
Are you eventually looking for Registration Sources?
If so, please see the AnyConcreteTypeNotAlreadyRegisteredSource:
var builder = new ContainerBuilder();
builder.RegisterSource(new AnyConcreteTypeNotAlreadyRegisteredSource());
var container = builder.Build();
though I'm willing to use other frameworks
You can use the Unity container. It allows you to build objects of any class (not interfaces) without explicitly registering the classes with the container. Of course the classes have to be public, non-abstract, have a public constructor, and interface-based dependencies should be registered with the container.
Here is a sample code:
public interface IService
{
}
public class Service : IService
{
}
public class MyClass
{
private readonly IService m_Service;
public MyClass(IService service)
{
m_Service = service;
}
}
class Program
{
static void Main(string[] args)
{
UnityContainer container = new UnityContainer();
container.RegisterType<IService, Service>(); //We need to register interface-based dependency
var my_class = container.Resolve<MyClass>(); //We can resolve class-based types without registering them explicitly
}
}
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();
I want to inject Container property via SimpleInjector. I didn't find any functionality of SimpleInjector for that.
Then I wanted to register self container to itself, but Container has no interface.
I want this functionality because I don't to transfer Container object via constructor - because why if I can use auto inject of register objects.
My usage idea:
var container = new Container();
container.Options.AutowirePropertiesWithAttribute<InjectableProperty>();
container.Register<ISomething, Something>(Lifestyle.Singleton);
ISomething:
public interface ISomething
{
void SomeMethod();
}
Something class:
public class Something : ISomething
{
public void SomeMethod()
{
var environment = _container.GetInstance<IEnvironment>();
environment.DoSomething();
}
[InjectableProperty] // - maybe it is not possible (I don't know it)
Container Container {get;set;}
}
Do you have any idea to achieve that?
Thank you very much.
Prevent having your application code depend upon the container. The only place in your application that should know about the existence of your DI library is the Composition Root (the place where you register all your dependencies).
Instead of letting each class call back into the container (which is called the Service Locator anti-pattern), prefer using Dependency Injection. With Dependency Injection you inject dependencies instead of asking for them.
So you can rewrite your class to the following:
public class Something : ISomething
{
private readonly IEnvironment environment;
public Something (IEnvironment environment)
{
this.environment = environment;
}
public void SomeMethod()
{
this.environment.DoSomething();
}
}
Also, prevent doing any logic in your constructors besides storing the incoming dependencies. This allows you to compose object graphs with confidence.
In some cases however, it can still be useful to inject the Container into another class. For instance when creating a factory class that is located inside the Composition Root. In that case you can still use constructor injection, like this:
// Defined in an application layer
public interface IMyFactory
{
IMyService CreateService();
}
// Defined inside the Composition Root
public class MyFactory : IMyFactory
{
private readonly Container container;
public MyFactory(Containter container)
{
this.container = container;
}
public IMyService CreateService(ServiceType type)
{
return type == ServiceType.A
? this.container.GetInstance<MyServiceA>()
: this.container.GetInstance<MyServiceB>();
}
}
If Simple Injector detects a Container constructor argument, it will inject itself into the constructor automatically.
Within the bootstrapper class of my WebApi I'm trying to register a new instance of a class called 'Facade' based on its interface type.
Within this type being regitered it requires a new instance of 'CRUDOperator' which also has a new instance of 'Adaptor' in its constructor. Is what I'm trying to do possible? I am currently just recieving an exception that the overload params are incorrect.
public static class Bootstrapper
{
public static void Initialise()
{
var container = BuildUnityContainer();
GlobalConfiguration.Configuration.DependencyResolver = new Unity.WebApi.UnityDependencyResolver(container);
}
private static IUnityContainer BuildUnityContainer()
{
var container = new UnityContainer();
*****ERROR*****
container.RegisterType<IFacade,Facade>(new CRUDOperatorSelector(new Adapter()));
return container;
}
}
Unity is capable of resolving concrete types without registering them, so if in Your case the types CRUDOperatorSelector and Adapter are concrete types (and I'm assuming they are) you just have to register the type Facade as implementation of IFacade and resolve it. Unity will then create an instance of each dependency and pass it to the constructor of Facade.
If some of those types implement an abstraction (an interface or an abstract class) register them also.
Warning, long post ahead.
I've been thinking a lot about this lately and I'm struggling to find a satisfying solution here. I will be using C# and autofac for the examples.
The problem
IoC is great for constructing large trees of stateless services. I resolve services and pass the data only to the method calls. Great.
Sometimes, I want to pass a data parameter into the constructor of a service. That's what factories are for. Instead of resolving the service I resolve its factory and call create method with the parameter to get my service. Little more work but OK.
From time to time, I want my services to resolve to the same instance within a certain scope. Autofac provides InstancePerLifeTimeScope() which is very handy. It allows me to always resolve to the same instance within an execution sub-tree. Good.
And there are times when I want to combine both approaches. I want data parameter in constructor and have have the instances scoped. I have not found a satisfying way to accomplish this.
Solutions
1. Initialize method
Instead of passing data into the constructor, just pass it to Initialize method.
Interface:
interface IMyService
{
void Initialize(Data data);
void DoStuff();
}
Class:
class MyService : IMyService
{
private Data mData;
public void Initialize(Data data)
{
mData = data;
}
public void DoStuff()
{
//...
}
}
Registration:
builder.RegisterType<MyService>().As<IMyService>().InstancePerLifetimeScope();
Usage:
var myService = context.Resolve<IMyService>();
myService.Init(data);
// somewhere else
var myService = context.Resolve<IMyService>();
After resolving the service for the first time and calling Initialize I can happily resolve within the same context and get the same initialized instance. I don't like the fact that before calling Initialize I have an unusable object. There is a danger that the instance will be resolved and used somewhere else before I call Initialize().
2. Holder pattern
This is a pattern that holds a reference to the data object and instead of injecting the data object itself I inject the holder object.
Interface:
interface IMyService
{
void DoStuff();
}
Class:
class MyService : IMyService
{
private Data mData;
public MyService(IDataHolder dataHolder)
{
mData = dataHolder.Data;
}
public void DoStuff()
{
//...
}
}
Registration:
builder.RegisterType<MyService>().As<IMyService>();
builder.RegisterType<DataHolder>().As<IDataHolder>().InstancePerLifetimeScope();
Usage:
var holder = context.Resolve<IDataHolder>();
holder.Data = data;
// somewhere else
var myService = context.Resolve<IMyService>();
This is a little bit better as I moved the responsibility of holding an instance to a different class. I can now use the holder in other services too. Other advantage is that I can hot swap data in holder if necessary. I don't like the fact that it obfuscates the code and adds another interface I have to mock during testing.
3. Let container hold the instance
Interface:
interface IMyService
{
void DoStuff();
}
Class:
class MyService : IMyService
{
private Data mData;
public MyService(Data data)
{
mData = dataHolder.Data;
}
public void DoStuff()
{
//...
}
}
Registration:
builder.RegisterType<MyService>().As<IMyService>().InstancePerLifetimeScope();
Usage:
var myServiceFactory = context.Resolve<Func<Data, IMyService>>();
myServiceFactory(data);
// somewhere else
var myService = context.Resolve<IMyService>();
That's right. I don't store the result of a factory call anywhere, because autofac stores it for me. This is pretty surprising to anybody who will read the code. I'm not sure if autofac was even meant to be used like this. Nice thing about this is that I need neither an extra initialize method nor extra class for holding instance.
Question
What is your take on this? How do you handle a situation with run-time data parameters and lifetime scoping? Am I missing a better approach?
Autofac now supports this out of the box with an extension to the lifetime scopes. The BeginLifetimeScope() method has an overload that takes an Action<ContainerBuilder> that allows for adding new registrations specific to only that lifetime scope. So for the given example it would look something like:
var builder = new ContainerBuilder();
builder.RegisterType<MyService>().As<IMyService>().InstancePerLifetimeScope();
var container = builder.Build();
using(var scope = container.BeginLifetimeScope(
builder =>
{
builder.RegisterInstance(new Data(....));
}))
{
// References to 'IMyService' will always be resolved to the same instance within this lifetime scop
// References to 'Data' will be resolved to the instance registered just for this lifetime scope.
var svc = scope.Resolve<IMyService>();
}
Most of the time, runtime data is the non static info you need to pass in any process, like x in a math function, so the easiest way to deal with it is using a parameter in the function:
class MyService : IMyService
{
public MyService(){}
public void DoStuff(Data mData)
{
//...
}
}
var myService = context.Resolve<IMyService>();
myService.DoStuff(data);
But, assuming your example is just a example and you are asking because your class need to keep runtime data to run more processes and you don't wanna to pass the same argument in every function:
1.- If you don't loose the scope of the runtime data in every Resolve you can resolve with TypedParameter:
Ej:
//initilization
var builder = new ContainerBuilder();
builder.RegisterType<MyService>().As<IMyService>().InstancePerLifetimeScope();
var container = builder.Build();
//any point of your app
Data mData = new Data("runtimeData"); // must to be accesible in every place you Resolve
using(var scope = container.BeginLifetimeScope())
{
var service = scope.Resolve<IMyService>(new TypedParameter(typeof(Data), mData));
service.DoStuff();
}
using(var scope = container.BeginLifetimeScope())
{
var service2 = scope.Resolve<IMyService>(new TypedParameter(typeof(Data), mData));
service2.DoStuff();
}
2.- If you don't have a reference to runtime data in every place you are resolving you can RegisterInstance when and where you create runtime data. Autofac should inyect mData instance thanks to Direct Depency Policy
//initilization
var builder = new ContainerBuilder();
builder.RegisterType<MyService>().As<IMyService>().InstancePerLifetimeScope();
var container = builder.Build();
//where you create or modify runtime data. When runtime data changes you have to update the container again.
var mData = new Data("runtimeData");
updatedBuilder= new ContainerBuilder();
updatedBuilder.RegisterInstance(mData).As<Data>
updatedBuilder.Update(builder);
//in any point of your app
using(var scope = updatedBuilder.BeginLifetimeScope())
{
var service = scope.Resolve<IMyService>();
service.DoStuff();
}
//in any other point of your app
using(var scope = updatedBuilder.BeginLifetimeScope())
{
var service2 = scope.Resolve<IMyService>();
service2.DoStuff();
}
My take on this is that you've done about as good as you can do. The only niggle that I have about it is that Autofac doesn't really do a great job of helping you manage those lifetime scopes, so you're stuck calling their BeginLifetimeScope somewhere. And they can be nested.
Ninject, on the other hand, does some really cool stuff that doesn't require turning your brain inside-out. Their named scope extension makes it possible for you to create a (gasp) named scope and bind the lifetime of objects within that scope. If you are using factories (clearly you are, judging from the question) you'll also want to use the context preservation extension, so that stuff activated out of factories gets the lifetime management from the named scope that the factory was activated within. Bindings wind up looking something like this:
var scopeName = "Your Name Here";
Bind<TopLevelObject>().ToSelf().DefinesNamedScope(ScopeName);
Bind<ISomeScopedService>().To<SomeScopedService>().InNamedScope(ScopeName);
// A minor bit of gymnastics here for factory-activated types to use
// the context-preservation extension.
Bind<FactoryActivatedType>().ToSelf().InNamedScope(ScopeName);
Bind<IFactoryActivatedType>().ToMethod(x => x.ContextPreservingGet<FactoryActivatedType>());
The nice part about this is that the scope of those bindings is specifically tied to the named scope rather than just being tied to whatever the nearest lifetime scope up the chain is. IMHO, it makes the lifetimes of those objects much more predictable.
Many IoC frameworks support registration of a factory function (or lambda expression), that takes as one of its arguments an instance of the container / scope / resolution context itself.
This allows using additional levels of indirection, as well as the use of information that uniquely identifies the context or scope. Additionally many provide hooks, like event handlers or the option to derive from a life cycle scope class, to interact with a scope being started or ended.
Principle
For AutoFac and your specific example, the following principle would work, using additional levels of indirection in registration.
// Inject `Data` instance resolved from current scope.
builder.Register<IMyService>(ctx => new MyService(ctx.Resolve<Data>()));
// Extra level of indirection, get a "factory" for a 'Data' instance.
builder.Register<Data>(ctx => ctx.Resolve<Func<Data>>()()).InstancePerLifetimeScope();
// The indirection resolves to a map of scopes to "factory" functions.
builder.Register<Func<Data>>(ScopedDataExtensions.GetFactory);
We can use any available unique property on a context / scope to construct this mapping.
// Maps scopes to data "factories".
public static class ScopedDataExtensions
{
private static readonly ConcurrentDictionary<object, Func<Data>> _factories = new ConcurrentDictionary<object, Fund<Data>>();
public static Func<Data> GetFactory(this IComponentContext ctx)
{
var factory = default(Func<Data>);
return _factories.TryGetValue(ctx.ComponentRegistry, out factory) ? factory : () => null;
}
public static void SetFactory(this ILifetimeScope scope, Func<Data> factory)
{
_factories[scope.ComponentRegistry] = factory;
}
}
We can use it like this to supply "local" data instances to be injected into our scoped service instances.
var myData = new Data("nested");
nestedScope.SetFactory(() => myData);
// ...
var myService = nestedScope.Resolve<IMyService>();
A more complete and generic example for AutoFac follows below.
Generic extension class for this pattern
public static class AutofacScopeExtensions
{
// Map from context => factories per type
public static readonly ConcurrentDictionary<object, ConcurrentDictionary<Type, object>> _factories =
new ConcurrentDictionary<object, ConcurrentDictionary<Type, object>>();
private static class ScopedFactoryFor<T>
{
public static Func<T> DefaultFactory = () => default(T);
public static Func<T> GetFactory(ConcurrentDictionary<Type, object> fromContext)
{
object factory;
return (fromContext.TryGetValue(typeof(T), out factory)) ? (Func<T>)factory : DefaultFactory;
}
}
public static IRegistrationBuilder<T, SimpleActivatorData, SingleRegistrationStyle>
WithContextFactoryFor<T>(this ContainerBuilder builder, Func<T> defaultFactory = null)
{
if (defaultFactory != null)
ScopedFactoryFor<T>.DefaultFactory = defaultFactory;
builder.Register<Func<T>>(AutofacScopeExtensions.GetFactory<T>);
return builder.Register<T>(ctx => ctx.Resolve<Func<T>>()());
}
public static IContainer BuildContainer(this ContainerBuilder builder)
{
var container = builder.Build();
container.ChildLifetimeScopeBeginning += OnScopeStarting;
return container;
}
public static ILifetimeScope SetScopeFactory<T>(this ILifetimeScope scope, Func<T> factory)
{
ScopeMapFor(scope)[typeof(T)] = factory;
return scope;
}
public static ILifetimeScope SetScopeValue<T>(this ILifetimeScope scope, T instance)
{
return SetScopeFactory(scope, () => instance);
}
public static Func<T> GetFactory<T>(IComponentContext ctx)
{
return ScopedFactoryFor<T>.GetFactory(ScopeMapFor(ctx));
}
private static ConcurrentDictionary<Type, object> ScopeMapFor(IComponentContext ctx)
{
return _factories.GetOrAdd(ctx.ComponentRegistry, x => new ConcurrentDictionary<Type, object>());
}
private static void OnScopeStarting(object sender, LifetimeScopeBeginningEventArgs evt)
{
evt.LifetimeScope.ChildLifetimeScopeBeginning += OnScopeStarting;
evt.LifetimeScope.CurrentScopeEnding += OnScopeEnding; // so we can do clean up.
}
private static void OnScopeEnding(object sender, LifetimeScopeEndingEventArgs evt)
{
var map = default(ConcurrentDictionary<Type, object>);
if (_factories.TryRemove(evt.LifetimeScope.ComponentRegistry, out map))
map.Clear();
}
}
Allowing the following syntax for registration:
builder.WithContextFactoryFor<Data>(() => new Data("Default")).InstancePerLifetimeScope();
builder.Register<IMyService>(ctx => new MyService(ctx.Resolve<Data>()));
And resolve like:
// ...
var myData = new Data("Some scope");
// ...
context.SetScopeFactory(() => myData);
// ...
// Will inject 'myData' instance.
var myService = context.Resolve<IMyService>();
Simpler Alternative
If you explicitly start nested scopes and at the time you do, you know how the scoped Data instance is to be created, you can skip the extension class and register the "factory" delegate with the nested scope when you create it:
var nestedScope = container.BeginLifetimeScope(
"L2",
x => x.RegisterInstance<Func<Data>>(() => new Data("nested")));
If I understand you correctly you want to use factories by delegating object creation to container while passing some parameters to its constructor.
This is implemented in Castle Windsor with typed factory facility.
Example classes we want to resolve:
public interface IMyService
{
void Do();
}
public class MyService : IMyService
{
private readonly Data _data;
private readonly IDependency _dependency;
public MyService(Data data, IDependency dependency)
{
_data = data;
_dependency = dependency;
}
public void Do()
{
throw new System.NotImplementedException();
}
}
public class Data
{
}
public interface IDependency
{
}
public class Dependency : IDependency
{
}
We create a factory interface:
public interface IMyServiceFactory
{
IMyService Create(Data data);
void Release(IMyService service);
}
We won't be implementing this interface because Castle Windsor will be generating an implementation with Dynamic Proxy. There's an important detail here: parameter name(data) in factory method and the one in the constructor should match.
Then we do the registration and try to resolve the values.
[Test]
public void ResolveByFactory()
{
WindsorContainer container = new WindsorContainer();
container.AddFacility<TypedFactoryFacility>();
container.Register(Component.For<IMyServiceFactory>().AsFactory());
container.Register(Component.For<IMyService>().ImplementedBy<MyService>().LifestyleScoped());
container.Register(Component.For<IDependency>().ImplementedBy<Dependency>().LifestyleScoped());
IMyServiceFactory factory = container.Resolve<IMyServiceFactory>();
IMyService myService1;
IMyService myService2;
using (container.BeginScope())
{
myService1 = factory.Create(new Data());
myService2 = factory.Create(new Data());
myService1.Should().BeSameAs(myService2);
}
using (container.BeginScope())
{
IMyService myService3 = factory.Create(new Data());
myService3.Should().NotBeSameAs(myService1);
myService3.Should().NotBeSameAs(myService2);
}
}
You will see that the object created in the same scope are the same references. Let me know if this is the behaviour you want.