AutoFac - создание незарегистрированного сервиса с известными сервисами - PullRequest
4 голосов
/ 18 февраля 2011

Создание незарегистрированного сервиса с известными сервисами (внедрение их через ctr).

Я хочу избежать загрязнения контейнера.

Ответы [ 3 ]

7 голосов
/ 09 августа 2011

Вот еще один способ разрешения незарегистрированных типов бетона из контейнера.Обратите внимание, что все конструкторы автозапуска, находящие и выбирающие логику, все обработчики событий регистрации остаются в силе.

Сначала вы определяете этот метод:

    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);
        }
    }

Идея состоит в том, что вы получаете регистрацию компонента из производногоконтекст и решить его в текущем контексте.Затем вы можете создать несколько удобных перегрузок:

    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);
    }
3 голосов
/ 28 февраля 2011

Я нашел решение, которое требовало некоторого пользовательского кода.Что-то специфическое для моего приложения, но я думаю, что вы можете получить картину.

Resolve (parameter.ParameterType) будет вызовом вашего контейнера.

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.");
}
0 голосов
/ 17 декабря 2018

Вот способ разрешить незарегистрированный тип с помощью свойств известного конструктора (ctor). Это основано на предыдущем великом посте: https://stackoverflow.com/a/6994144/2641447. В этом решении абсолютно замечательно, что поиск и выбор логики конструктора выполняется Autofac.

Комментарий предназначен для устранения проблем, которые я решил с помощью функции 'ExternallyOwned ()', которая настраивает компонент таким образом, что экземпляры никогда не удаляются контейнером.

Я думаю, что улучшение решения может быть следующим:

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 Autofac;
using Autofac.Core;
using System;
using System.Collections.Generic;
...