How to resolve public class with internal constructor on AutoFac - autofac

I have this class to be instantiated in a unittest:
public class Customer
{
internal Customer(Guid id) {
// initialize property
}
}
If I instantiate the test class from another (unittests) assembly with a new Customer() works because I added [assembly: InternalsVisibleTo("MyProject.Tests")]
var sut = new Customer(Guid.NewGuid()); // works
But when i setup an autofac container in the other (unittest) assembly
var builder = new ContainerBuilder();
builder.RegisterType<Customer>().AsSelf();
var container = builder.Build();
I can't resolve with autofac.
var theParam = new NamedParameter("id", Guid.NewGuid());
_sut = container.Resolve<Customer>(theParam); // throws exception
My best guess was that the internal constructor was not available. But adding [assembly: InternalsVisibleTo("Autofac")] next to the other doesn't help.
The exception thown by Autofac is
Autofac.Core.DependencyResolutionException:
An error occurred during the activation of a particular registration. See the inner exception for details.
Registration: Activator = Customer (ReflectionActivator),
Services = [MyProject.Customer],
Lifetime = Autofac.Core.Lifetime.CurrentScopeLifetime,
Sharing = None,
Ownership = OwnedByLifetimeScope
---> No accessible constructors were found for the type 'MyProject.Customer'.
Can Autofac not handle internal constructors?

Autofac can't locate non-public constructors because it uses the DefaultConstructorFinder class which searches only for public constructors by default.
You have to create your custom implementation of the IConstructorFinder interface like this:
public class AllConstructorFinder : IConstructorFinder
{
private static readonly ConcurrentDictionary<Type, ConstructorInfo[]> Cache =
new ConcurrentDictionary<Type, ConstructorInfo[]>();
public ConstructorInfo[] FindConstructors(Type targetType)
{
var result = Cache.GetOrAdd(targetType,
t => t.GetTypeInfo().DeclaredConstructors.Where(c => !c.IsStatic).ToArray());
return result.Length > 0 ? result : throw new NoConstructorsFoundException(targetType);
}
}
Then you have to use the FindConstructorsWith extension method on type registration:
builder.RegisterType<Customer>()
.FindConstructorsWith(new AllConstructorFinder())
.AsSelf();
The InternalsVisibleToAttribute can't help in this case because it affects only the compile time.

if you want to register assembly types with at least only has one public constructor then you can use Autofac Where extension method like this.
builder.RegisterAssemblyTypes(assembly)
.Where(t => t.GetConstructors().Length > 0) //only public constructors
.AsImplementedInterfaces()
.InstancePerLifetimeScope();
Note: PublicOnly extension method registers only public types.

Related

Concrete type instance registration in Autofac fails to resolve in a nested scope when using AnyConcreteTypeNotAlreadyRegisteredSource source

I have an Autofac container that uses "AnyConcreteTypeNotAlreadyRegisteredSource" to allow resolution of any concrete type without explicit need to register it. If I register a singleton instance of a concrete type using the RegisterInstance method, there are no issues with the resolution. However, if I create a child lifetime scope and do the same concrete type singleton instance registration, the child lifetime scope is not able to resolve the type anymore. It throws the following exception:
Autofac.Core.Activators.Reflection.NoConstructorsFoundException: 'No accessible constructors were found for the type 'AutofacTests.IssueTests+Manager'.'
Why is it even trying to instantiate the object when I have a singleton instance of that type registered already? It seems like this problem only comes when I try to resolve a concrete type instead of an interface.
Here is the test code that demonstrates the problem (The test method name and comments show what works and what does not):
using Autofac;
using Autofac.Features.ResolveAnything;
namespace AutofacTests
{
[TestClass]
public class IssueTests
{
private interface IPerson
{
}
private class Employee : IPerson
{
public Employee()
{
}
}
private class Manager : Employee
{
internal Manager(IPerson worker)
{
string s = "";
}
}
[TestMethod]
public void Resolution_ThatWorks()
{
ContainerBuilder builder = new ContainerBuilder();
var mgr = new Manager(null);
builder.RegisterInstance<IPerson>(mgr);
builder.RegisterInstance<Manager>(mgr);
using (var container = builder.Build())
{
var person = container.Resolve<Manager>();
Assert.IsNotNull(person, "Employee could not be resolved!");
}
}
[TestMethod]
public void ResolutionWithAnyTypeSource_ThatWorks()
{
ContainerBuilder builder = new ContainerBuilder();
// NOTE: This source registration does not impact the concrete type resolution when no child lifetime scope is involved.
builder.RegisterSource(new AnyConcreteTypeNotAlreadyRegisteredSource());
var mgr = new Manager(null);
builder.RegisterInstance<IPerson>(mgr);
builder.RegisterInstance<Manager>(mgr);
using (var container = builder.Build())
{
var person = container.Resolve<Manager>();
Assert.IsNotNull(person, "Employee could not be resolved!");
}
}
[TestMethod]
public void NestedResolution_ThatWorks()
{
ContainerBuilder builder = new ContainerBuilder();
using (var container = builder.Build())
{
void RegisterNestedServices(ContainerBuilder builder)
{
var mgr = new Manager(null);
builder.RegisterInstance<IPerson>(mgr);
builder.RegisterInstance<Manager>(mgr);
}
using (var childContainer = container.BeginLifetimeScope(RegisterNestedServices))
{
var person = childContainer.Resolve<Manager>();
Assert.IsNotNull(person, "Employee could not be resolved!");
}
}
}
[TestMethod]
public void NestedResolutionWithAnyTypeSource_ThatFails()
{
ContainerBuilder builder = new ContainerBuilder();
// NOTE: This source registration causes the resolution of a concrete type to fail in a child lifetime scope.
builder.RegisterSource(new AnyConcreteTypeNotAlreadyRegisteredSource());
using (var container = builder.Build())
{
void RegisterNestedServices(ContainerBuilder builder)
{
var mgr = new Manager(null);
builder.RegisterInstance<IPerson>(mgr);
builder.RegisterInstance<Manager>(mgr);
}
using (var childContainer = container.BeginLifetimeScope(RegisterNestedServices))
{
// Works
var person = childContainer.Resolve<IPerson>();
Assert.IsNotNull(person, "Person could not be resolved!");
// *** Fails ***
var emp = childContainer.Resolve<Manager>();
Assert.IsNotNull(emp, "Employee could not be resolved!");
}
}
}
}
}
Anyone has any idea what am I doing wrong or how to make this work in the child lifetime scopes?
Thanks.
It appears you're hitting this known issue where AnyConcreteTypeNotAlreadyRegisteredSource (ACTNARS) doesn't properly look at new registrations in child scopes.
At the time of this writing there is not a fix for it, but we'd love a PR to get it fixed. It's been open for a while now.

Warning CS0618: 'ComplexTypeModelBinder' is obsolete

In .NET Core 3 I extended ComplexTypeModelBinder class to create custom model binder for a specific class.
Main target was to override creation of model instance via CreateModel method.
public MyModelBinder: ComplexTypeModelBinder
{
// Constructor here...
protected override object CreateModel(ModelBindingContext bindingContext)
{
// Create model instance based on custom condition.
}
}
After an upgrade to .NET 5, I'm receiving a compilation warning to replace ComplexTypeModelBinder with ComplexObjectModelBinder:
warning CS0618: 'ComplexTypeModelBinder' is obsolete: 'This type is obsolete and will be removed in a future version. Use ComplexObjectModelBinder instead.'
The problem is that ComplexObjectModelBinder is sealed class and CreateModel method is internal, so subclass approach cannot work any more.
The solution I settled for is to create class MyModelBinder which implement IModelBinder interface and acts as a wrapper around ComplexObjectModelBinder. ComplexObjectModelBinder is passed in MyModelBinder as constructor parameter.
Same approach is used for MyModelBinderProvider and ComplexObjectModelProvider.
Later, instead of overriding CreateMethod of ComplexObjectModelBinder, which is not possible in .NET 5, just assign bindingContext.Model in the wrapper method BindAsyncModel of MyModelBinder, before passing the bindingContext to ComplexObjectModelBinder's BindAsyncModel. This will make ComplexObjectModelBinder use model that is passed in, instead of creating default new instance.
public class MyModelBinder: IModelBinder
{
private readonly ComplexObjectModelBinder _binder;
public MyModelBinder(ComplexObjectModelBinder binder)
{
_binder = binder;
}
public Task BindModelAsync(ModelBindingContext bindingContext)
{
MyModel myModel = // custom instantiation logic here
bindingContext.Model = myModel;
return _binder.BindModelAsync(bindingContext);
}
}
For the registration of the custom model binder provider, first we find existing, automatically registered ComplexObjectBinderProvider, use it in costructor of MyModelBinderProvider and then insert MyModelBinderProvider in front of ComplexObjectBinderProvider.
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews(options => {
// more configurations here...
var bindingProvider = options.ModelBinderProviders.First(provider =>
provider is ComplexObjectModelBinderProvider) as ComplexObjectModelBinderProvider;
var indexOf = options.ModelBinderProviders.IndexOf(bindingProvider);
options.ModelBinderProviders.Insert(indexOf, new MyModelBinderProvider(bindingProvider));
}
}

Autofac fails to resolve enumerable of typed HttpClients

I have a number of services which require usage of typed HttpClient from HttpClientFactory.
Though I can resolve one service I can't resolve IEnumerable of this services.
interface IMyHttpClient
{
}
class MyHttpClient: IMyHttpClient
{
public MyHttpClient(HttpClient client)
{
}
}
class Program
{
static void Main(string[] args)
{
var services = new ServiceCollection();
services.AddHttpClient()
.AddHttpClient<IMyHttpClient, MyHttpClient>();
var builder = new ContainerBuilder();
// Exception goes away when remove this line
builder.RegisterType<MyHttpClient>().As<IMyHttpClient>();
builder.Populate(services);
var provider = builder.Build();
// ============== This works
// provider.Resolve<IMyHttpClient>();
// ============== This throws exception
provider.Resolve<IEnumerable<IMyHttpClient>>();
}
}
Constructor will be called once and than exception is thrown:
```
DependencyResolutionException: None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'ConsoleApp2.MyHttpClient' can be invoked with the available services and parameters:
Cannot resolve parameter 'System.Net.Http.HttpClient client' of constructor 'Void .ctor(System.Net.Http.HttpClient)'.
```
The issue is that AddHttpClient adds it's own registration of IMyHttpClient. But I do want to register using Autofac only! Is there a way to use typed clients but still stay with Autofac?
The exception explains that Autofac can't resolve parameter 'System.Net.Http.HttpClient client'. I suppose this is because such type wasn't registered in your container for second resgistration of IMyHttpClient. To save an advantages of HttpClientFactory you can register excplicit constructor parameter for example like this:
static void Main(string[] args)
{
var services = new ServiceCollection();
services.AddHttpClient();
var builder = new ContainerBuilder();
// exclicit resolving client for constructor
builder.RegisterType<MyHttpClient>().As<IMyHttpClient>().WithParameter(
(p, ctx) => p.ParameterType == typeof(HttpClient),
(p, ctx) => ctx.Resolve<IHttpClientFactory>().CreateClient());
builder.Populate(services);
var provider = builder.Build();
// ============== This works
provider.Resolve<IMyHttpClient>();
// ============== This works too
provider.Resolve<IEnumerable<IMyHttpClient>>();
}
In this example Resolve<IEnumerable<IMyHttpClient>> return enumeration with single IMyHttpClient, that is initialized with HttpClient from core HttpClientFactory.
UPD: the post was updated by #norekhov comment

Large number of SQL Active Sessions when injecting DBContext using Autofac in WebApi

I'm using Autofac for injecting dependencies in Web Api.
I set InstancePerRequest scope for EF DBContext.
Autofac Wiring up configuration:
public void Configuration(IAppBuilder app)
{
ConfigureOAuth(app);
var config = new HttpConfiguration();
var builder = new ContainerBuilder();
builder.RegisterApiControllers(Assembly.GetExecutingAssembly()).InstancePerRequest();
var asmb = typeof (TrafficDataService).Assembly;
builder.RegisterAssemblyTypes(asmb).Where(t => t.Name.EndsWith("Service")).AsImplementedInterfaces().InstancePerRequest();
builder.RegisterType<TrafficServiceGlobalContext>().As<IUnitOfWork>().InstancePerRequest();
builder.RegisterType<EMSEntities>().As<IEmsDataModel>().InstancePerRequest();
builder.RegisterType<ViolationTrafficEntities>().As<IViolationDataModel>().InstancePerRequest();
builder.RegisterType<TrafficController>().As<IHttpController>().InstancePerRequest();
builder.Register(c => HttpContext.Current.GetOwinContext().Authentication).InstancePerRequest();
builder.Register(c => app.GetDataProtectionProvider()).InstancePerRequest();
var container = builder.Build();
config.DependencyResolver = new AutofacWebApiDependencyResolver(container);
app.UseAutofacMiddleware(container);
app.UseAutofacWebApi(config);
app.UseCors(Microsoft.Owin.Cors.CorsOptions.AllowAll);
app.UseWebApi(config);
WebApiConfig.Register(config);
}
After Service gets huge number of request, and when checking Active Sessions for my DB i see 500 Active Sessions over db.
Is really this a problem?
How to implement Connection Pooling?
Any idea?
Update:
All relevant classes depends on interfaces.
As Yacoub Massad asked in comments area, here is some of relevant classes signature and constructors:
public partial class ViolationTrafficEntities : DbContext, IViolationDataModel
{
.
.
.
}
public class TrafficDataService : ITrafficDataService
{
private readonly IViolationDataModel _violationDataModel;
public TrafficDataService(IViolationDataModel violationDataModel)
{
_violationDataModel = violationDataModel;
}
}

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.