Unity:隐式ResolvedParameter用于未命名的注册

 Fier田野莎莎 发布于 2023-01-26 04:37

UserService构造函数有两个参数,一个是IUnitOfWorkIUserRepository:

public UserService(IUnitOfWork unitofWork, IUserRepository userRepository) 
{ ... }

我使用命名注册来区分多个实例IUnitOfWork,因此在UserService使用Unity容器注册时,我需要使用以下命令显式指定参数InjectionConstructor:

container.RegisterType(
    new InjectionConstructor(
        new ResolvedParameter("someContext"),
        new ResolvedParameter()
    )
);

有可能new ResolvedParameter()被省略吗?我希望Unity隐式推导出这个参数,因为不需要命名注册. 代码如下所示:

container.RegisterType(
    new InjectionConstructor(
        new ResolvedParameter("someContext")
    )
);

当我不需要使用时,这将完成InjectionConstructor.

1 个回答
  • 基于InjectionConstructor,我想出了这个RequiredInjectionConstructor.它允许您指定任何参数集,并且它将尝试查找需要(至少)传递的注入参数集的构造函数.如果有多个构造函数符合此条件,则会选择具有最少参数的构造函数.假设其余构造函数参数是未命名的已解析参数.

    我还没有对它进行全套的单元测试,所以如果你遇到任何问题,请告诉我.

    /// <summary>
    /// A class that holds the collection of minimum required
    /// parameters for a constructor, so that the container can
    /// be configured to call this constructor.
    /// </summary>
    public class RequiredInjectionConstructor : InjectionMember
    {
        private readonly List<InjectionParameterValue> _requiredParameterValues;
    
        /// <summary>
        /// Create a new instance of <see cref="RequiredInjectionConstructor"/> that looks
        /// for a constructor with a minimum of the given required set of parameters.
        /// </summary>
        /// <param name="requiredParameterValues">The values for the parameters, that will
        /// be converted to <see cref="InjectionParameterValue"/> objects.</param>
        public RequiredInjectionConstructor(params object[] requiredParameterValues)
        {
            _requiredParameterValues = InjectionParameterValue.ToParameters(requiredParameterValues).ToList();
        }
    
        /// <summary>
        /// Add policies to the <paramref name="policies"/> to configure the
        /// container to call this constructor with the required parameter values.
        /// </summary>
        /// <param name="serviceType">Interface registered, ignored in this implementation.</param>
        /// <param name="implementationType">Type to register.</param>
        /// <param name="name">Name used to resolve the type object.</param>
        /// <param name="policies">Policy list to add policies to.</param>
        public override void AddPolicies(Type serviceType, Type implementationType, string name, IPolicyList policies)
        {
            ConstructorInfo ctor = FindConstructor(implementationType, _requiredParameterValues);
            IEnumerable<InjectionParameterValue> selectedConstructorParameterValues = GetSelectedConstructorParameterValues(ctor, _requiredParameterValues);
    
            policies.Set<IConstructorSelectorPolicy>(
                new SpecifiedConstructorSelectorPolicy(ctor, selectedConstructorParameterValues.ToArray()),
                new NamedTypeBuildKey(implementationType, name));
        }
    
        private static ConstructorInfo FindConstructor(Type typeToCreate, IEnumerable<InjectionParameterValue> requiredInjectionParameters)
        {
            var typeToCreateReflector = new ReflectionHelper(typeToCreate);
    
            var matchedConstructors = typeToCreateReflector.InstanceConstructors.
                Where(ctor =>
                {
                    var constructorParameterTypes = ctor.GetParameters().Select(info => info.ParameterType);
                    return requiredInjectionParameters.All(required => constructorParameterTypes.Any(required.MatchesType));
                });
    
            if (matchedConstructors.Any())
            {
                // Prefer the constructor that has the least number of arguments.
                // Other preference models could be implemented here. 
                return matchedConstructors.OrderBy(ctor => 
                    ctor.GetParameters().Count()).
                    FirstOrDefault();
            }
    
            string signature = string.Join(", ", requiredInjectionParameters.Select(required => required.ParameterTypeName).ToArray());
    
            throw new InvalidOperationException(
                string.Format("Unable to find a constructor with the minimum required parameters.  Type: {0}, RequiredParameters: {1}",
                    typeToCreate.FullName,
                    signature));
        }
    
        private static IEnumerable<InjectionParameterValue> GetSelectedConstructorParameterValues(ConstructorInfo ctor, IEnumerable<InjectionParameterValue> requiredInjectionParameters)
        {
            var injectionParameterValues = new List<InjectionParameterValue>();
    
            foreach (var parameter in ctor.GetParameters())
            {
                var existingInjectionParameter = requiredInjectionParameters.FirstOrDefault(required => required.MatchesType(parameter.ParameterType));
                injectionParameterValues.Add(existingInjectionParameter ?? new ResolvedParameter(parameter.ParameterType));
            }
    
            return injectionParameterValues;
        }
    }
    

    2023-01-26 11:05 回答
撰写答案
今天,你开发时遇到什么问题呢?
立即提问
热门标签
PHP1.CN | 中国最专业的PHP中文社区 | PNG素材下载 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有