If I have the following class, is it possible to exclude the copy constructor from Autofac registration?
public class A
{
public A() {}
public A(A other) { // copy constructor }
public A(int b) { // some other stuff }
}
Basically, I would want autofac to resolve the default constructor, or if the user requested a Func<int, A>
the third constructor. I never want autofac to resolve the copy constructor. Is this possible?
The reason for this is that when I try and use Autofac to inject a Func<A>
, it results in a circular dependency as Autofac is trying to use the second constructor (it thinks it knows a way to resolve A, but the way to resolve A requires an A).
You can implement your own constructor selector that ignores your second constructor:
public class AConstructorSelector : IConstructorSelector
{
public ConstructorParameterBinding SelectConstructorBinding(ConstructorParameterBinding[] constructorBindings)
{
if (constructorBindings == null) throw new ArgumentNullException("constructorBindings");
if (constructorBindings.Length == 0) throw new ArgumentOutOfRangeException("constructorBindings");
if (constructorBindings.Length == 1)
return constructorBindings[0];
var withLength = constructorBindings
.Where(b => !b.TargetConstructor.GetParameters().Select(p => p.ParameterType).Contains(typeof(A)))
.Select(binding => new { Binding = binding, ConstructorParameterLength = binding.TargetConstructor.GetParameters().Length })
.ToArray();
var maxLength = withLength.Max(binding => binding.ConstructorParameterLength);
var maximal = withLength
.Where(binding => binding.ConstructorParameterLength == maxLength)
.Select(ctor => ctor.Binding)
.ToArray();
if (maximal.Length == 1)
return maximal[0];
throw new DependencyResolutionException("Unable to find constructor");
}
}
And when register your class use it as parameter of the UsingConstructor
var builder = new ContainerBuilder();
builder.RegisterType<A>().UsingConstructor(new AConstructorSelector());
See fiddle
Autofac 3.x will automatically create Implicit Relationship Types , eg Func<A>
, Lazy<B>
, etc. However you can override the default by registering your own.
builder.Register<Func<int, A>>(c => (value) => { return new A(value); });
This is registering the Func<int, A>
signature and instructing which constructor to use to create this.
Try it out at .NET Fiddle, https://dotnetfiddle.net/CTFyo3
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.