添加Unity DI框架后Umbraco后台报错:UmbracoAuthorizeAttribute构造函数歧义
我在Umbraco解决方案中通过NuGet引入了Unity DI框架,我的Unity配置代码如下:
public static class UnityConfig { #region Unity Container private static Lazy<IUnityContainer> container = new Lazy<IUnityContainer>(() => { var container = new UnityContainer(); RegisterTypes(container); return container; }); public static IUnityContainer Container => container.Value; #endregion public static void RegisterTypes(IUnityContainer container) { container.RegisterType<IHomeViewModelFactory, HomeViewModelFactory>(new PerResolveLifetimeManager()); } }
网站能正常启动,但访问Umbraco后台时抛出错误:
The type UmbracoAuthorizeAttribute has multiple constructors of length 1. Unable to disambiguate.
完整错误日志如下:
ERROR Umbraco.Core.UmbracoApplicationBase - An unhandled exception occurred Unity.Exceptions.ResolutionFailedException: Resolution of the dependency failed, type = 'Umbraco.Web.Mvc.UmbracoAuthorizeAttribute', name = '(none)'. Exception occurred while: while resolving. Exception is: InvalidOperationException - The type UmbracoAuthorizeAttribute has multiple constructors of length 1. Unable to disambiguate. ----------------------------------------------- At the time of the exception, the container was: Resolving Umbraco.Web.Mvc.UmbracoAuthorizeAttribute,(none) ---> System.InvalidOperationException: The type UmbracoAuthorizeAttribute has multiple constructors of length 1. Unable to disambiguate. at Unity.ObjectBuilder.BuildPlan.Selection.ConstructorSelectorPolicyBase`1.FindLongestConstructor(Type typeToConstruct) at Unity.ObjectBuilder.BuildPlan.Selection.ConstructorSelectorPolicyBase`1.SelectConstructor(IBuilderContext context, IPolicyList resolverPolicyDestination) at Unity.ObjectBuilder.BuildPlan.DynamicMethod.Creation.DynamicMethodConstructorStrategy.CreateInstanceBuildupExpression(DynamicBuildPlanGenerationContext buildContext, IBuilderContext context)
这个问题的核心是Unity的默认构造函数选择逻辑:它会优先挑选参数数量最多的构造函数来实例化对象,但UmbracoAuthorizeAttribute恰好有两个参数数量相同(都只接受1个参数)的构造函数,导致Unity无法自动判断该用哪一个。下面是两种直接有效的解决办法:
方法1:明确指定UmbracoAuthorizeAttribute的构造函数
在你的UnityConfig.RegisterTypes方法里,添加对UmbracoAuthorizeAttribute的注册,直接告诉Unity要使用哪个构造函数。如果想使用无参构造函数,代码如下:
container.RegisterType<UmbracoAuthorizeAttribute>(new InjectionConstructor());
如果需要使用带特定参数的构造函数(比如接受日志服务的那个),可以这样写:
container.RegisterType<UmbracoAuthorizeAttribute>( new InjectionConstructor(typeof(ILogger<UmbracoAuthorizeAttribute>)) );
方法2:让Unity直接调用指定的实例化逻辑
另一种方式是通过InjectionFactory,让Unity直接使用你指定的方式创建UmbracoAuthorizeAttribute实例,跳过它的自动构造函数选择逻辑:
container.RegisterType<UmbracoAuthorizeAttribute>( new InjectionFactory(_ => new UmbracoAuthorizeAttribute()) );
这种方式更直接,相当于手动控制了实例的创建过程,避免Unity在构造函数选择上出错。
额外建议
如果后续还遇到Umbraco其他内部类型的类似构造函数歧义问题,可以考虑统一配置Unity对Umbraco.Web或Umbraco.Core命名空间下的类型采用自定义解析策略,不过一般来说,针对单个类型手动指定构造函数就足够解决问题了。
内容的提问来源于stack exchange,提问作者brinch

