AutoFac - 使用已知服务实例化未注册的服务

时间:2011-02-18 15:28:18

标签: ioc-container autofac

使用已知服务实例化未注册的服务(通过ctr注入它们)。

我想避免容器污染。

3 个答案:

答案 0 :(得分:7)

以下是从容器中解析未注册的具体类型的另一种方法。请注意,所有autofac构造函数都在查找和选择逻辑,所有注册事件处理程序仍然有效。

首先,您定义此方法:

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

答案 1 :(得分:3)

我找到了一个需要一些自定义代码的解决方案。某些事情是我的应用程序特有的,但我认为你可以得到图片。

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

答案 2 :(得分:0)

这是一种使用已知构造函数(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;