为什么 Unity 在解析 class 时无法 select String 构造函数?
Why does Unity fail to select a String constructor when resolving class?
我已经在 (.NET 4.5.2) 项目中将 Unity 从 v4.0.1 升级到 v5.11.3,该项目之前运行良好,但自从升级后出现以下异常:
Resolution failed with error: Failed to select a constructor for System.String
我试图解析的 class 有一个字符串构造函数,我已经用 InjectionConstructor
注册了它。请参阅下面的代码:
// Multiple IDbContext registrations happen when the application is initialized
container.RegisterType<IDbContext, AuthenticationContext>(typeof(AuthenticationContext).ToString(), new InjectionConstructor(AppConstants.DatabaseKey));
container.RegisterType<IDbContext, ApplicationContext>(typeof(ApplicationContext).ToString(), new InjectionConstructor(AppConstants.DatabaseKey));
public class DbContextFactory : IDbContextFactory
{
private readonly IUnityContainer _container;
public DbContextFactory(IUnityContainer container)
{
_container = container;
}
public IDbContext CreateDbContext<TDbContext>() where TDbContext : IDbContext
{
var key = typeof(TDbContext).ToString();
return container.Resolve<TDbContext>(key);
}
}
public class AuthenticationContext : DbContextWrapper
{
public AuthenticationContext(string connectionString) : base(connectionString)
{
}
}
public class DbContextWrapper : IDbContext
{
public DbContextWrapper(string connectionString)
{
}
}
我应该如何解释异常?无法 select String 的构造函数,让我认为注册成功并且它正在寻找接受 String 但找不到的构造函数?这很奇怪,因为我的 AuthenticationContext 只有一个接受……字符串的构造函数!
我尝试在 dotnetfiddle 上阐明完整的代码示例,但在初始化 UnityContainer 时出现 "Operation could destabilize the runtime" 异常。参见 https://dotnetfiddle.net/xuX57K
所以我在通过 container.EnableDebugDiagnostic();
启用调试模式后收到的新异常消息让我开始思考......它说我必须配置容器为构造函数提供字符串值,我确信我做过。所以这意味着它实际上甚至没有考虑使用我的注册。在调试容器注册时,我看到我的注册在那里,所以这也不是问题。
然后我意识到 Unity 默认注册所有类型,所以它试图创建 AuthenticationContext
的实例,因此失败了,因为当它使用隐式注册时,它不知道如何处理必需的字符串参数。
错误在 DbContextFactory
中并已修复:
public IDbContext CreateDbContext<TDbContext>() where TDbContext : IDbContext
{
var key = typeof(TDbContext).ToString();
// This is wrong because it is trying to resolve AuthenticationContext for a given name.
// But it should resolve a registration for IDbContext for that name since that is
// how it was registered!
// return container.Resolve<TDbContext>(key);
return container.Resolve<IDbContext>(key);
}
我已经在 (.NET 4.5.2) 项目中将 Unity 从 v4.0.1 升级到 v5.11.3,该项目之前运行良好,但自从升级后出现以下异常:
Resolution failed with error: Failed to select a constructor for System.String
我试图解析的 class 有一个字符串构造函数,我已经用 InjectionConstructor
注册了它。请参阅下面的代码:
// Multiple IDbContext registrations happen when the application is initialized
container.RegisterType<IDbContext, AuthenticationContext>(typeof(AuthenticationContext).ToString(), new InjectionConstructor(AppConstants.DatabaseKey));
container.RegisterType<IDbContext, ApplicationContext>(typeof(ApplicationContext).ToString(), new InjectionConstructor(AppConstants.DatabaseKey));
public class DbContextFactory : IDbContextFactory
{
private readonly IUnityContainer _container;
public DbContextFactory(IUnityContainer container)
{
_container = container;
}
public IDbContext CreateDbContext<TDbContext>() where TDbContext : IDbContext
{
var key = typeof(TDbContext).ToString();
return container.Resolve<TDbContext>(key);
}
}
public class AuthenticationContext : DbContextWrapper
{
public AuthenticationContext(string connectionString) : base(connectionString)
{
}
}
public class DbContextWrapper : IDbContext
{
public DbContextWrapper(string connectionString)
{
}
}
我应该如何解释异常?无法 select String 的构造函数,让我认为注册成功并且它正在寻找接受 String 但找不到的构造函数?这很奇怪,因为我的 AuthenticationContext 只有一个接受……字符串的构造函数!
我尝试在 dotnetfiddle 上阐明完整的代码示例,但在初始化 UnityContainer 时出现 "Operation could destabilize the runtime" 异常。参见 https://dotnetfiddle.net/xuX57K
所以我在通过 container.EnableDebugDiagnostic();
启用调试模式后收到的新异常消息让我开始思考......它说我必须配置容器为构造函数提供字符串值,我确信我做过。所以这意味着它实际上甚至没有考虑使用我的注册。在调试容器注册时,我看到我的注册在那里,所以这也不是问题。
然后我意识到 Unity 默认注册所有类型,所以它试图创建 AuthenticationContext
的实例,因此失败了,因为当它使用隐式注册时,它不知道如何处理必需的字符串参数。
错误在 DbContextFactory
中并已修复:
public IDbContext CreateDbContext<TDbContext>() where TDbContext : IDbContext
{
var key = typeof(TDbContext).ToString();
// This is wrong because it is trying to resolve AuthenticationContext for a given name.
// But it should resolve a registration for IDbContext for that name since that is
// how it was registered!
// return container.Resolve<TDbContext>(key);
return container.Resolve<IDbContext>(key);
}