Resolve Autofac factory based on multiple constructors - autofac

Does anybody know what's missing to make this test work?
It's a pitty that it doesn't work out of the box.
class A { }
class B { public B(A a) { } }
class C { public C(B b) { } }
[Test]
public void SuperFactoryResolutionTest()
{
var builder = new ContainerBuilder();
builder.RegisterType<B>();
builder.RegisterType<C>();
using (var container = builder.Build())
{
Assert.DoesNotThrow(() =>
{
var factory = container.Resolve<Func<A, C>>();
var x = factory(new A());
});
}
}

No this is not supported by Autofac.
You can only pass direct dependencies when calling Resolve. So you cannot ad-hoc specify dependencies deep down in the hierarchy chain.
Anyway this is against the inversion of control principle: C should only know about B and should not know that somewhere an A is used by B. So when you ask for a C you also should not tell which A to use.
However you can achieve somewhat similar with manually building the resolution chain:
This is the closest what you can get:
var intermediateFactory = container.Resolve<Func<B,C>>();
Func<A, C> factory =
a => intermediateFactory(container.Resolve<B>(TypedParameter.From(a)));
var x = factory(new A());

Related

Singleton per string ctor parameter value, for both class A and dependent class B instances

I need to create a single instance, not based on the type or a lifetime scope decl, but on the value of a string parameter to the ctor. I also need this same effect for a dependent instance of another class, using the same string in its own unrelated ctor.
class A {
public A(string appId, B b) {}
}
class B {
public B(string appId) {}
}
In the above example, I need to create an A singleton and a B singleton, for unique values of appId.
I can resolve A and B with a TypedParameter, but the singleton-per-appId-value part I can't figure out. I tried just A alone to simplify (without dependent B involved). I looked at Keyed, Indexed, etc in the docs but none seemed to fit singleton-per-some-user-defined-key-value, unless I write my own Register lambda that uses my own memory cache of unique appId keys.
Does Autofac have a built-in terse way to enforce this?
There is not going to be a good solution to this because dependency injection is generally based on types, not parameter values. It's not the same as, say, setting up caching for a web app based on parameter values. More specifically, Autofac does not have anything "baked in" that will help you. (Nor, to my knowledge, does any other DI framework.)
Likely what you're going to need to do is create a tiny factory that does the caching for you and use that.
Here's an example that I'm not compiling and not testing but is coming off the top of my head to get you unblocked.
First, you'd need to create a little factory for your B class.
public class BFactory
{
private ConcurrentDictionary<string, B> _cache = new ConcurrentDictionary<string, B>();
public B GetB(string appId)
{
return this._cache.GetOrAdd(
appId,
a => new B(a));
}
}
Now you'll register BFactory as singleton, which will get you the one-instance-per-app-ID behavior you want. Register B as a lambda and it can use parameters.
builder.RegisterType<BFactory>().SingleInstance();
builder.Register((c, p) =>
{
var appId = p.Named<string>("appId");
var factory = c.Resolve<BFactory>();
return factory.GetB(appId);
});
Now you can resolve a B as long as there's a parameter passed to Resolve, like
using var scope = container.BeginLifetimeScope();
var b = scope.Resolve<B>(new NamedParameter("appId", "my-app-id"));
You can build something similar for A, but the AFactory can take a BFactory as a parameter so it can get the right instance of A.
public class AFactory
{
private ConcurrentDictionary<string, B> _cache = new ConcurrentDictionary<string, B>();
private readonly BFactory _factory;
public AFactory(BFactory factory)
{
this._factory = factory;
}
public A GetA(string appId)
{
return this._cache.GetOrAdd(
appId,
a => new A(a, this._factory.GetB(a)));
}
}
Same thing here, register the factory as a singleton and get A from the factory.
builder.RegisterType<AFactory>().SingleInstance();
builder.Register((c, p) =>
{
var appId = p.Named<string>("appId");
var factory = c.Resolve<AFactory>();
return factory.GetA(appId);
});
You can get fancy with it, too, like using the Func relationships if there are some things that need to come from the container. For example, let's say your B class really looks like this:
public class B
{
public B(string appId, IComponent fromContainer) { /* ... */ }
}
In there, maybe IComponent needs to come from the container but the appId comes from a parameter. You could make the BFactory be like this:
public class BFactory
{
private ConcurrentDictionary<string, B> _cache = new ConcurrentDictionary<string, B>();
private ILifetimeScope _scope;
public BFactory(ILifetimeScope scope)
{
// This will be the CONTAINER / root scope if BFactory
// is registered as a singleton!
this._scope = scope;
}
public B GetB(string appId)
{
return this._cache.GetOrAdd(
appId,
a => {
// Auto-generated factory! It will get IComponent from
// the container but let you put the string in as a parameter.
var func = this._scope.Resolve<Func<string, B>>();
return func(a);
});
}
}
Be aware if you use that auto-generated factory thing (the Func<string, B> thing) that you will need to register B by itself, like:
// You can't register the factory as the provider for B
// because it's cyclical - the BFactory will want to resolve
// a Func<string, B> which, in turn, will want to execute the
// BFactory.
builder.RegisterType<B>();
builder.RegisterType<BFactory>().SingleInstance();
That means you'd have to switch your code around to take a BFactory instead of a B. You can probably monkey with it to make it work, but you get the idea - you're going to have to make the caching mechanism yourself and that's what you'll hook into Autofac. Hopefully the above snippets can give you some ideas you can expand on and get you unblocked.

How can I register a (boundless) type hierarchy using Autofac?

I've got a Factory interface (along with concrete implementations):
// foo.dll
interface IFooProvider
{
T GetFoo<T>()
where T : BaseFoo;
}
My BaseFoo is not abstract, but only its subclasses are actually useful:
// shared.dll
class BaseFoo
{ ... }
I've also got a (potentially unbounded) number of subclasses of BaseFoo across many assemblies:
// foo.dll
class AFoo : BaseFoo
{ ... }
// foo2.dll
class BFoo : BaseFoo
{ ... }
... and many more ...
Naively, I had been registering the Foo-derived classes in an unsurprising way:
// foo.dll
class ConcreteFooRegistration : Module
{
protected override void Load(ContainerBuilder builder)
{
// a concrete FooProvider is registered elsewhere
builder.Register(c => c.Resolve<IFooProvider>().GetFoo<AFoo>());
builder.Register(c => c.Resolve<IFooProvider>().GetFoo<BFoo>());
...
}
}
But this implies that:
the assembly containing ConcreteFooRegistration (e.g. foo.dll) also contains some/all of AFoo, BFoo, etc.
the assembly containing ConcreteFooRegistration (e.g. foo.dll) references the assemblies (e.g. foo2.dll) containing some/all of AFoo, BFoo, etc.
IFooProvider be available to any other assembly containing BaseFoo-derived classes and the Module that registers them
For sake of discussion, assume that none of these is possible and/or desirable. That is, I'm looking for solutions other than "move IFooProvider into shared.dll".
Since AFoo and BFoo are the real dependencies that other types are interested in, and IFooProvider is (from that perspective) just an instantiation detail, I got inspired by the Autofac+Serilog integration that Nicholas came up with. I've used a similar approach elsewhere, so I wrote up an AttachToComponentRegistration() implementation:
// foo.dll
class ConcreteFooRegistration : Module
{
// NOTICE: there's no Load() method
protected override void AttachToComponentRegistration(...)
{
...
registration.Preparing += (sender, e) =>
{
var pFoo = new ResolvedParameter(
(p, i) => p.ParameterType.IsAssignableTo<BaseFoo>(),
(p, i) => i.Resolve<IFooProvider>().GetFoo<FooWeNeed>()
);
e.Parameters = new [] { pFoo }.Concat(e.Parameters);
};
}
}
This was successful, in that I was able to remove all the individual BaseFoo-derived registrations from ConcreteFooRegistration and still successfully resolve arbitrary BaseFoo-derived dependencies with constructor injection:
// other.dll:
class WorkerRegisteration : Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterType<Worker>();
// NOTICE: FooYouDidntKnowAbout is NOT explicitly registered
}
}
class Worker
{
public Worker(FooYouDidntKnowAbout foo)
{ ... }
...
}
BUT: now I can't arbitrarily resolve AFoo outside of constructor injection:
builder.Register(c =>
{
// here's one use for a BaseFoo outside constructor injection
var foo = c.Resolve<AFoo>();
if (foo.PropValue1)
return new OtherClass(foo.PropValue2);
else
return new YetAnother(foo.PropValue3);
}
...
builder.Register(c =>
{
// here's another
var foo = c.Resolve<AFoo>();
return c.Resolve(foo.TypePropValue);
});
Assuming that publishing IFooProvider as a public export of foo.dll or moving it to shared.dll is undesirable/impossible, thus eliminating the naive-but-unsurprising implementation above, (how) can I set up my registrations to be able to resolve arbitrary subclasses of BaseFoo from anywhere?
Thanks!
I think what you're looking for is a registration source. A registration source is a dynamic "registration provider" you can use to feed Autofac registrations as needed.
As of this writing, the doc on registration sources is pretty thin (I just haven't gotten a chance to write it) but there's a blog article with some details about it.
Registration sources are how Autofac supports things like IEnumerable<T> or Lazy<T> - we don't require you actually register every collection, instead we dynamically feed the registrations into the container using sources.
Anyway, let me write you up a sample here and maybe I can use it later to massage it into the docs, eh? :)
First, let's define a very simple factory and implementation. I'm going to use "Service" instead of "Foo" here because my brain stumbles after it sees "foo" too many times. That's a "me" thing. But I digress.
public interface IServiceProvider
{
T GetService<T>() where T : BaseService;
}
public class ServiceProvider : IServiceProvider
{
public T GetService<T>() where T : BaseService
{
return (T)Activator.CreateInstance(typeof(T));
}
}
OK, now let's make the service types. Obviously for this sample all the types are sort of in one assembly, but when your code references the type and the JIT brings it in from some other assembly, it'll work just the same. Don't worry about cross-assembly stuff for this.
public abstract class BaseService { }
public class ServiceA : BaseService { }
public class ServiceB : BaseService { }
Finally, a couple of classes that consume the services, just so we can see it working.
public class ConsumerA
{
public ConsumerA(ServiceA service)
{
Console.WriteLine("ConsumerA: {0}", service.GetType());
}
}
public class ConsumerB
{
public ConsumerB(ServiceB service)
{
Console.WriteLine("ConsumerB: {0}", service.GetType());
}
}
Good.
Here's the important bit, now: the registration source. The registration source is where you will:
Determine if the resolve operation is asking for a BaseService type or not. If it's not, then you can't handle it so you'll bail.
Build up the dynamic registration for the specific type of BaseService derivative being requested, which will include the lambda that invokes the provider/factory to get the instance.
Return the dynamic registration to the resolve operation so it can do the work.
It looks like this:
using Autofac;
using Autofac.Core;
using Autofac.Core.Activators.Delegate;
using Autofac.Core.Lifetime;
using Autofac.Core.Registration;
public class ServiceRegistrationSource : IRegistrationSource
{
public IEnumerable<IComponentRegistration> RegistrationsFor(
Service service,
Func<Service, IEnumerable<IComponentRegistration>> registrationAccessor)
{
var swt = service as IServiceWithType;
if(swt == null || !typeof(BaseService).IsAssignableFrom(swt.ServiceType))
{
// It's not a request for the base service type, so skip it.
return Enumerable.Empty<IComponentRegistration>();
}
// This is where the magic happens!
var registration = new ComponentRegistration(
Guid.NewGuid(),
new DelegateActivator(swt.ServiceType, (c, p) =>
{
// The factory method is generic, but we're working
// at a reflection level, so there's a bit of crazy
// to deal with.
var provider = c.Resolve<IServiceProvider>();
var method = provider.GetType().GetMethod("GetService").MakeGenericMethod(swt.ServiceType);
return method.Invoke(provider, null);
}),
new CurrentScopeLifetime(),
InstanceSharing.None,
InstanceOwnership.OwnedByLifetimeScope,
new [] { service },
new Dictionary<string, object>());
return new IComponentRegistration[] { registration };
}
public bool IsAdapterForIndividualComponents { get{ return false; } }
}
It looks complex, but it's not too bad.
The last step is to get the factory registered as well as the registration source. For my sample, I put those in an Autofac module so they're both registered together - it doesn't make sense to have one without the other.
public class ServiceProviderModule : Autofac.Module
{
protected override void Load(ContainerBuilder builder)
{
builder.RegisterType<ServiceProvider>().As<IServiceProvider>();
builder.RegisterSource(new ServiceRegistrationSource());
}
}
Finally, let's see it in action. If I throw this code into a console app...
static void Main()
{
var builder = new ContainerBuilder();
builder.RegisterType<ConsumerA>();
builder.RegisterType<ConsumerB>();
builder.RegisterModule<ServiceProviderModule>();
var container = builder.Build();
using(var scope = container.BeginLifetimeScope())
{
var a = scope.Resolve<ConsumerA>();
var b = scope.Resolve<ConsumerB>();
}
}
What you end up with on the console is:
ConsumerA: ServiceA
ConsumerB: ServiceB
Note I had to register my consuming classes but I didn't explicitly register any of the BaseService-derived classes - that was all done by the registration source.
If you want to see more registration source samples, check out the Autofac source, particularly under the Autofac.Features namespace. There you'll find things like the CollectionRegistrationSource, which is responsible for handling IEnumerable<T> support.

Register delegate-func by convention

On the ContainerBuilder i can do the following:
builder.Register<ScenariosConfig>(c =>
(ScenariosConfig)c.Resolve<ConfigFactory>()
.Create(typeof(ScenariosConfig)))
.SingleInstance();
With assembly scanning i can do the following:
builder.RegisterAssemblyTypes(assemblies)
.Where(HasSingletonAttribute)
.As(t => GetNameMatchingInterfaces(t))
.SingleInstance();
Now the question: Is there any way to achieve the following: ?
builder.RegisterAssemblyTypes(assemblies)
.Where(... some condition)
.CreateByDelegate((container, type)
=> c.Resolve<ConfigFactory>().Create(type))
.SingleInstance();
I've already found out about IRegistrationSource with which i can achieve something similar. However, I'm a bit skeptic about the performance impact of creating ton's of IRegistrationSource's for each of my conventions which require a delegate for creation...
And also there's the fact that IRegistrationSource can't be used whenever you need to resolve all instances of IFoo which should be bound by such a "convention".
In the end we did choose to use an IRegistrationSource. The only alternative i've "found" would have been to detect all types per reflection (not using autofac API...) and then generating a delegate for each and registering this with autofac. Would not really result in code that easily understandable...
So for completeness sake' here's the IRegistrationSource implementation:
public class ConfigConventionRegistrationSource : IRegistrationSource
{
public IEnumerable<IComponentRegistration> RegistrationsFor(
Service service,
Func<Service, IEnumerable<IComponentRegistration>> registrationAccessor)
{
var s = service as IServiceWithType;
if (s != null
&& s.ServiceType.IsClass
&& s.ServiceType.Name.EndsWith("Config")
&& !s.ServiceType.GetInterfaces().Any())
{
yield return RegistrationBuilder
.ForDelegate((componentContext, parameters) =>
CreateConfigByFactory(componentContext, s.ServiceType))
.As(s.ServiceType)
.SingleInstance()
.CreateRegistration();
}
}
private static object CreateConfigByFactory(
IComponentContext componentContext,
Type configType)
{
IConfig configFactory = componentContext.Resolve<IConfig>();
MethodInfo method = Reflector<IConfig>
.GetMethod(x => x.Load<object>())
.GetGenericMethodDefinition()
.MakeGenericMethod(configType);
try
{
return method.Invoke(configFactory, new object[0]);
}
catch (TargetInvocationException tex)
{
ExceptionDispatchInfo
.Capture(tex.InnerException)
.Throw();
throw; // will not be reached as thrown above ;-)
}
}
public bool IsAdapterForIndividualComponents
{
get { return false; }
}
}

autofac: IEnumerable<Lazy<IFoo, IFooMetaData>> --> Lazy.Value(with runtime param)?

Using Autofac, I have multiple IFoo components that take a run-time parameter in the constructor. I'm using some Metadata from the types along with the run-time parameter to construct and manage running instances.
interface IFoo
{
int RunTimeId { get; }
}
[FooMeta("ShaqFoo")]
class Foo1 : IFoo
{
public Foo1 (int runtTimeId)
{
...
}
[FooMeta("KungFoo")]
class Foo2 : IFoo
{
public Foo2 (int runtTimeId)
{
...
}
Module/Registration something like:
builder.Register<Func<int, Foo1>>(c =>
{
var cc = c.Resolve<IComponentContext>();
return id => cc.Resolve<Foo1>(TypedParameter.From<int>(id));
})
.As<Func<int, IFoo>>()
.WithMetadata<IFooMetaData>(m => m.For(sm => sm.FooType, typeof(Foo1)));
builder.Register<Func<int, Foo2>>(c =>
{
var cc = c.Resolve<IComponentContext>();
return id => cc.Resolve<Foo2>(TypedParameter.From<int>(id));
})
.As<Func<int, IFoo>>()
.WithMetadata<IFooMetaData>(m => m.For(sm => sm.FooType, typeof(Foo2)));
And a component that creates new Foos with the run-time parameters and metadata. I need to be create ALL IFoos for a given run-time parameter, and need to check for existing instances (essentially using Metadata + RunTimeId as a key) before creating.
public class FooActivator
{
public FooActivator(IEnumerable<Lazy<Func<int, IFoo>, IFooMetaData>> fooFactories)
{
m_FooFactories = fooFactories;
}
private void HandleNewRunTimeIdEvent(int id)
{
CreateFoosForNewId(id);
}
private void CreateFoosForNewId(int id)
{
foreach (var fooFactory in m_FooFactories)
{
if (!FooWithThisMetadataAndIdExists(fooFactory.Metadata.FooType, id))
{
var newFoo = fooFactory.Value(id);
}
}
}
}
Obviously, I can enumerate all of the IFoos and check metadata using the Lazy Enumeration, but can't pass in the run-time parameter to Lazy.Value. Seems like I need to pass in an Enumerable of Func<>s somehow, but can't figure out how to attach the metadata. Or maybe I need an entirely different approach?
Just getting my head wrapped around autofac, and hoping there's a clean way to accomplish this. I could settle for just using the concrete Foo type (instead of metadata) if there's a simple way to enumerate all of them (without creating them), and use the type + run-time Id as my key instead.
Updated the code with a working solution. Figured out how to register Factories properly with metadata. Seems to work.

Autofac wiring question - beginner

Beginners question:
Given two classes: Myclass5 and Myclass6 how can one wire up following factory method (returned as Func)
such that
myclass5 and myclass6 instances and IMyClass that they depend on are all retrieved via autofac (assuming that these three instances are registered).
public static MyClass4 FactoryMethod(int nu)
{
if (nu == 1)
return new MyClass5(....);
if (nu == 4)
return new MyClass6(....);
throw new NotImplementedException();
}
public abstract class MyClass4
{
}
public class MyClass5 : MyClass4
{
public MyClass5(int nu, IMyClass a)
{
}
}
public class MyClass6 : MyClass4
{
public MyClass6(int nu, IMyClass a)
{
}
}
For FactoryMethod to be able to create the instances, it requires access to a container. I would suggest create a delegate type for the factory method, which makes it easy to take dependency on it. Registration goes like this:
var cb = new ContainerBuilder();
cb.RegisterType<SomeClass>().As<IMyClass>();
cb.RegisterType<MyClass5>();
cb.RegisterType<MyClass6>();
cb.Register((c, p) =>
{
var context = c.Resolve<IComponentContext>();
return new FactoryMethod(nu =>
{
var nuParameter = TypedParameter.From(nu);
switch (nu)
{
case 1:
return context.Resolve<MyClass5>(nuParameter);
case 4:
return context.Resolve<MyClass6>(nuParameter);
default:
throw new NotImplementedException();
}
});
});
var container = cb.Build();
At resolve time, you can then take a dependency on the FactoryMethod delegate type and use it to resolve instances:
var factory = container.Resolve<FactoryMethod>();
var instance5 = factory(1);
var instance6 = factory(1);
Note: the delegate instance we're creating needs a context. We cannot use the c parameter directly since that context is only temporary. Thus we must resolve a IComponentContext to "bake" into the lambda.
Update: if you would like to extract the factory implementation into a method that is not dependent on the container I would suggest the following:
public class FactoryMethodImpl
{
readonly Func<int, MyClass5> _factory5;
readonly Func<int, MyClass6> _factory6;
public FactoryMethodImpl(Func<int, MyClass5> factory5, Func<int, MyClass6> factory6)
{
_factory5 = factory5;
_factory6 = factory6;
}
public MyClass4 Create(int nu)
{
switch (nu)
{
case 1:
return _factory5(nu);
case 4:
return _factory6(nu);
default:
throw new NotImplementedException();
}
}
}
Now, change the registration code to this:
var cb = new ContainerBuilder();
cb.RegisterType<SomeClass>().As<IMyClass>();
cb.RegisterType<MyClass5>();
cb.RegisterType<MyClass6>();
cb.RegisterType<FactoryMethodImpl>().SingleInstance();
cb.Register(c=> new FactoryMethod(c.Resolve<FactoryMethodImpl>().Create));