向接收 ArgumentException 的 Autofac 注册 Keyed 实现(类型 X 不可分配给服务 Y)
Register Keyed implementation with Autofac receiving an ArgumentException (Type X not assignable to service Y)
我正在使用 Autofac Keyed 选项注册一些具体类型。在我向类型和接口添加通用参数之前,这一切似乎都运行良好。
我的注册是这样的:
builder.RegisterType<Customer.DataAccess.Database.StoreElasticConnectionManagerByCompany>();
builder.RegisterType<Customer.DataAccess.Database.StoreElasticConnectionManagerByStore>();
builder.RegisterType<Customer.DataAccess.Database.StoreElasticConnectionManager>();
builder.RegisterType<Customer.DataAccess.Database.DatabaseManagement>().As<IDatabaseManagement>();
builder.RegisterType<ConnectionManagerFactory<Customer.DataAccess.Database.StoreElasticConnectionManagerByStore>>()
.Keyed<IConnectionManagerFactory<IConnectionManager>>(DatabaseConnectionShardingTypes.StoreDatabaseByStoreId);
builder.RegisterType<ConnectionManagerFactory<Customer.DataAccess.Database.StoreElasticConnectionManagerByCompany>>()
.Keyed<IConnectionManagerFactory<IConnectionManager>>(DatabaseConnectionShardingTypes.StoreDatabaseByCompanyId);
builder.RegisterType<DatabaseManagement>().As<IDatabaseManagement>().SingleInstance();
具体的类型和接口是这样实现的:
/*The factories*/
public interface IConnectionManagerFactory<T>
where T : IConnectionManager
{}
public class ConnectionManagerFactory<T> : IConnectionManagerFactory<T>
where T : IConnectionManager
{}
/*The Connection Manager*/
public interface IConnectionManager
{}
public abstract class StoreElasticConnectionManager : IConnectionManager
{}
public class StoreElasticConnectionManagerByStore : StoreElasticConnectionManager
{}
当我尝试 运行 我的代码时(当注册正在执行时)我收到以下错误:
An unhandled exception of type 'System.ArgumentException' occurred in
Autofac.dll
Additional information: The type
'Customer.DataAccess.Database.ConnectionManagerFactory1[Customer.DataAccess.Database.StoreElasticConnectionManagerByStore]'
is not assignable to service 'StoreDatabaseByStoreId
(Customer.DataAccess.Database.IConnectionManagerFactory
1[[Customer.DataAccess.Database.IConnectionManager,
Customer.DataAccess.Database, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=null]])'.
这可能是因为我已经将通用参数添加到 ConnectionManagerFactory
,因为在我这样做之前它就起作用了。
我试过添加以下内容:
builder.RegisterGeneric(typeof(Customer.DataAccess.Database.ConnectionManagerFactory<>))
.As(typeof(IConnectionManagerFactory<>));
但这似乎并没有解决问题。
关于如何进行的任何建议?
编辑
针对 nemesv 的问题,这是有效的代码,我没有使用泛型
builder.RegisterType<Customer.DataAccess.Database.StoreElasticConnectionManagerByCompany>();
builder.RegisterType<Customer.DataAccess.Database.StoreElasticConnectionManagerByStore>();
builder.RegisterType<Customer.DataAccess.Database.StoreElasticConnectionManager>();
builder.RegisterType<ConnectionManagerFactory<Customer.DataAccess.Database.StoreElasticConnectionManagerByStore>>()
.Keyed<IConnectionManagerFactory>(DatabaseConnectionShardingTypes.StoreDatabaseByStoreId);
builder.RegisterType<ConnectionManagerFactory<Customer.DataAccess.Database.StoreElasticConnectionManagerByCompany>>()
.Keyed<IConnectionManagerFactory>(DatabaseConnectionShardingTypes.StoreDatabaseByCompanyId);
如您所见,接口 IConnectionManagerFactory
不再通用。
具体 ConnectionManagerFactory
现在看起来像这样:
public class ConnectionManagerFactory<T> : IConnectionManagerFactory
where T : IConnectionManager
DatabaseConnectionShardingTypes
是一个简单的枚举。
我现在通过稍微更改代码并不再使用泛型解决了我的问题,但我仍然想知道我在上面的示例中做错了什么。
您正在尝试将 ConnectionManagerFactory<StoreElasticConnectionManagerByStore>
转换为 IConnectionManagerFactory<IConnectionManager>
您必须指定您的接口是协变的以允许此类强制转换,您可以使用 out
修饰符(有关详细信息,请参阅 "out T" vs. "T" in Generics)
public interface IConnectionManagerFactory<out T>
where T : IConnectionManager
{ }
如果您尝试以下代码行,您将遇到编译错误:
ConnectionManagerFactory<StoreElasticConnectionManagerByStore> c = null;
IConnectionManagerFactory<IConnectionManager> i = (ConnectionManagerFactory<StoreElasticConnectionManagerByStore>)c;
Cannot implicitly convert type 'ConnectionManagerFactory' to 'IConnectionManagerFactory'. An explicit conversion exists (are you missing a cast?)
添加 out
修饰符意味着您的界面不能在方法参数中接受 T
:
public interface IConnectionManagerFactory<out T>
where T : IConnectionManager
{
void Do1(T t); // not valid
T Do2(); // valid
}
如果您的 IConnectionManagerFactory<T>
不是协变的,您将不得不更改代码,例如拆分接口
我正在使用 Autofac Keyed 选项注册一些具体类型。在我向类型和接口添加通用参数之前,这一切似乎都运行良好。
我的注册是这样的:
builder.RegisterType<Customer.DataAccess.Database.StoreElasticConnectionManagerByCompany>();
builder.RegisterType<Customer.DataAccess.Database.StoreElasticConnectionManagerByStore>();
builder.RegisterType<Customer.DataAccess.Database.StoreElasticConnectionManager>();
builder.RegisterType<Customer.DataAccess.Database.DatabaseManagement>().As<IDatabaseManagement>();
builder.RegisterType<ConnectionManagerFactory<Customer.DataAccess.Database.StoreElasticConnectionManagerByStore>>()
.Keyed<IConnectionManagerFactory<IConnectionManager>>(DatabaseConnectionShardingTypes.StoreDatabaseByStoreId);
builder.RegisterType<ConnectionManagerFactory<Customer.DataAccess.Database.StoreElasticConnectionManagerByCompany>>()
.Keyed<IConnectionManagerFactory<IConnectionManager>>(DatabaseConnectionShardingTypes.StoreDatabaseByCompanyId);
builder.RegisterType<DatabaseManagement>().As<IDatabaseManagement>().SingleInstance();
具体的类型和接口是这样实现的:
/*The factories*/
public interface IConnectionManagerFactory<T>
where T : IConnectionManager
{}
public class ConnectionManagerFactory<T> : IConnectionManagerFactory<T>
where T : IConnectionManager
{}
/*The Connection Manager*/
public interface IConnectionManager
{}
public abstract class StoreElasticConnectionManager : IConnectionManager
{}
public class StoreElasticConnectionManagerByStore : StoreElasticConnectionManager
{}
当我尝试 运行 我的代码时(当注册正在执行时)我收到以下错误:
An unhandled exception of type 'System.ArgumentException' occurred in Autofac.dll
Additional information: The type 'Customer.DataAccess.Database.ConnectionManagerFactory
1[Customer.DataAccess.Database.StoreElasticConnectionManagerByStore]' is not assignable to service 'StoreDatabaseByStoreId (Customer.DataAccess.Database.IConnectionManagerFactory
1[[Customer.DataAccess.Database.IConnectionManager, Customer.DataAccess.Database, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]])'.
这可能是因为我已经将通用参数添加到 ConnectionManagerFactory
,因为在我这样做之前它就起作用了。
我试过添加以下内容:
builder.RegisterGeneric(typeof(Customer.DataAccess.Database.ConnectionManagerFactory<>))
.As(typeof(IConnectionManagerFactory<>));
但这似乎并没有解决问题。
关于如何进行的任何建议?
编辑
针对 nemesv 的问题,这是有效的代码,我没有使用泛型
builder.RegisterType<Customer.DataAccess.Database.StoreElasticConnectionManagerByCompany>();
builder.RegisterType<Customer.DataAccess.Database.StoreElasticConnectionManagerByStore>();
builder.RegisterType<Customer.DataAccess.Database.StoreElasticConnectionManager>();
builder.RegisterType<ConnectionManagerFactory<Customer.DataAccess.Database.StoreElasticConnectionManagerByStore>>()
.Keyed<IConnectionManagerFactory>(DatabaseConnectionShardingTypes.StoreDatabaseByStoreId);
builder.RegisterType<ConnectionManagerFactory<Customer.DataAccess.Database.StoreElasticConnectionManagerByCompany>>()
.Keyed<IConnectionManagerFactory>(DatabaseConnectionShardingTypes.StoreDatabaseByCompanyId);
如您所见,接口 IConnectionManagerFactory
不再通用。
具体 ConnectionManagerFactory
现在看起来像这样:
public class ConnectionManagerFactory<T> : IConnectionManagerFactory
where T : IConnectionManager
DatabaseConnectionShardingTypes
是一个简单的枚举。
我现在通过稍微更改代码并不再使用泛型解决了我的问题,但我仍然想知道我在上面的示例中做错了什么。
您正在尝试将 ConnectionManagerFactory<StoreElasticConnectionManagerByStore>
转换为 IConnectionManagerFactory<IConnectionManager>
您必须指定您的接口是协变的以允许此类强制转换,您可以使用 out
修饰符(有关详细信息,请参阅 "out T" vs. "T" in Generics)
public interface IConnectionManagerFactory<out T>
where T : IConnectionManager
{ }
如果您尝试以下代码行,您将遇到编译错误:
ConnectionManagerFactory<StoreElasticConnectionManagerByStore> c = null;
IConnectionManagerFactory<IConnectionManager> i = (ConnectionManagerFactory<StoreElasticConnectionManagerByStore>)c;
Cannot implicitly convert type 'ConnectionManagerFactory' to 'IConnectionManagerFactory'. An explicit conversion exists (are you missing a cast?)
添加 out
修饰符意味着您的界面不能在方法参数中接受 T
:
public interface IConnectionManagerFactory<out T>
where T : IConnectionManager
{
void Do1(T t); // not valid
T Do2(); // valid
}
如果您的 IConnectionManagerFactory<T>
不是协变的,您将不得不更改代码,例如拆分接口