question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Support multiple constructors with reflection-based component registration

See original GitHub issue

Support multiple constructors where the constructor parameters are able to be obtained from the container and based on the supplied autofac parameters. The variable nature of the autofac parameters would decide which constructor to select.

For example, given a simple type with two public constructors:

public class TwoConstructors
{
   readonly object _value;

   public TwoConstructors(IA value) => _value = value;
   public TwoConstructors(IB value) => _value = value;   
   public override string ToString() => _value.ToString();   
}

with simple types for the constructor parameters:

public interface IA { }
public interface IB { }
public class A : IA { public override string ToString() => "A"; }
public class B : IB { public override string ToString() => "B"; }

with reflection-based registration:

var containerBuilder = new ContainerBuilder();
containerBuilder.RegisterType<A>().As<IA>();
containerBuilder.RegisterType<B>().As<IB>();

It would be great if this reflection-based registration:

containerBuilder.RegisterType<TwoConstructors>();

would behave like this delegate-based registration:

containerBuilder.Register((componentContext, parameters) =>
{
   var ia = parameters.OfType<TypedParameter>().Where(typedParameter => typedParameter.Type == typeof(IA)).Select(typedParameter => (IA)typedParameter.Value).FirstOrDefault();
   if (ia != null)
      return new TwoConstructors(ia);

   var ib = parameters.OfType<TypedParameter>().Where(typedParameter => typedParameter.Type == typeof(IB)).Select(typedParameter => (IB)typedParameter.Value).FirstOrDefault();
   if (ib != null)
      return new TwoConstructors(ib);

   throw new DependencyResolutionException("Missing IA or IB parameter");
});

Today we receive the following expected exception:

  Unhandled Exception: Autofac.Core.DependencyResolutionException: An error occurred during the activation of a particular registration. See the inner exception for details. Registration: Activator = TwoConstructors (ReflectionActivator), Services = [TwoConstructors], Lifetime = Autofac.Core.Lifetime.CurrentScopeLifetime, Sharing = None, Ownership = OwnedByLifetimeScope ---> Cannot choose between multiple constructors with equal length 1 on type 'TwoConstructors'. Select the constructor explicitly, with the UsingConstructor() configuration method, when the component is registered.

Example usage (works with delegate-based registration):

var container = containerBuilder.Build();

Console.WriteLine(container.Resolve<TwoConstructors>(TypedParameter.From(container.Resolve<IA>())));
Console.WriteLine(container.Resolve<TwoConstructors>(TypedParameter.From(container.Resolve<IB>())));
Console.WriteLine(container.Resolve<TwoConstructors>()); // throws expected exception

Console.WriteLine(container.Resolve<Func<IA, TwoConstructors>>()(container.Resolve<IA>()));
Console.WriteLine(container.Resolve<Func<IB, TwoConstructors>>()(container.Resolve<IB>()));
Console.WriteLine(container.Resolve<Func<TwoConstructors>>()); // returns a func that will always throw the expected exception

Issue Analytics

  • State:closed
  • Created 6 years ago
  • Comments:6 (1 by maintainers)

github_iconTop GitHub Comments

1reaction
griffithtpcommented, Jul 31, 2019

+1

1reaction
zhangxin511commented, Jan 5, 2018

+1. Should be very helpful

Read more comments on GitHub >

github_iconTop Results From Across the Web

c# - Use Activator.CreateInstance() and support multiple ...
Now there is a new requirement: The constructor of myType can have multiple parameters. One of them has to accept an IConfiguration object....
Read more >
Registration Concepts — Autofac 7.0.0 documentation
When using reflection-based components, Autofac automatically uses the constructor for your class with the most parameters that are able to be obtained from ......
Read more >
Dependency Injection anti-pattern: multiple constructors
When Dependency Injection is applied correctly and completely, it is important that each type only has one constructor—multiple constructors ...
Read more >
Passing Parameters to Register
When you register a reflection-based component, the constructor of the type may require a parameter that can't be resolved from the container.
Read more >
How do I handle multiple constructors where each is ...
Normally, to do this I would set up a base class ( Shape ) and two derived classes ( ConfigurableParallelogram and DisplayOnlyParallelogram )....
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found