AutoFac - creating an unregistered service with known services

Creating an unregistered service with known services (entering them via ctr).

I want to avoid container pollution.

+4
source share
3 answers

Here is another way to allow unregistered specific types from a container. Please note that all autosamplers that search and select logic, all registration event handlers remain valid.

First you define this method:

public static object ResolveUnregistered(this IComponentContext context, Type serviceType, IEnumerable<Parameter> parameters) { var scope = context.Resolve<ILifetimeScope>(); using (var innerScope = scope.BeginLifetimeScope(b => b.RegisterType(serviceType))) { IComponentRegistration reg; innerScope.ComponentRegistry.TryGetRegistration(new TypedService(serviceType), out reg); return context.ResolveComponent(reg, parameters); } } 

The idea is that you get the component registration from the derived context and enable it in the current context. Then you can create some convenient overloads:

  public static object ResolveUnregistered(this IComponentContext context, Type serviceType) { return ResolveUnregistered(context, serviceType, Enumerable.Empty<Parameter>()); } public static object ResolveUnregistered(this IComponentContext context, Type serviceType, params Parameter[] parameters) { return ResolveUnregistered(context, serviceType, (IEnumerable<Parameter>)parameters); } public static TService ResolveUnregistered<TService>(this IComponentContext context) { return (TService)ResolveUnregistered(context, typeof(TService), Enumerable.Empty<Parameter>()); } public static TService ResolveUnregistered<TService>(this IComponentContext context, params Parameter[] parameters) { return (TService)ResolveUnregistered(context, typeof(TService), (IEnumerable<Parameter>)parameters); } 
+7
source

I found a solution requiring some kind of custom code. Somethings are specific to my application, but I think you can get the picture.

Resolve (parameter.ParameterType) will be a call to your container.

 public object ResolveUnregistered(Type type) { var constructors = type.GetConstructors(); foreach (var constructor in constructors) { try { var parameters = constructor.GetParameters(); var parameterInstances = new List<object>(); foreach (var parameter in parameters) { var service = Resolve(parameter.ParameterType); if (service == null) throw new NopException("Unkown dependency"); parameterInstances.Add(service); } return Activator.CreateInstance(type, parameterInstances.ToArray()); } catch (NopException) { } } throw new NopException("No contructor was found that had all the dependencies satisfied."); } 
+3
source

Here is a way to resolve an unregistered type using the properties of a well-known constructor (ctor). This is based on a previous great post: fooobar.com/questions/1340333 / .... In this solution, it is absolutely remarkable that Autofac performs the search and selection of constructor logic.

The comment aims to fix issues that I solved with ExternallyOwned (), which configures the component so that instances are never deleted by the container.

I think that improving the solution could be as follows:

 public static object ResolveUnregistered(this IComponentContext context, Type serviceType, IEnumerable<Parameter> parameters) { var scope = context.Resolve<ILifetimeScope>(); using (var innerScope = scope.BeginLifetimeScope(b => b.RegisterType(serviceType).ExternallyOwned())) return innerScope.Resolve(serviceType, parameters); } 

Using:

 using Autofac; using Autofac.Core; using System; using System.Collections.Generic; 
0
source

Source: https://habr.com/ru/post/1340333/


All Articles