我在 C# 中使用 Unity。我有一个名为 IConnectionStringLoader
的接口(interface),它有两个派生接口(interface)。
public interface IConnectionStringLoader
{
string Get();
void Write();
}
public interface IDbConnectionStringLoader : IConnectionStringLoader
{
}
public interface IMetaDataConnectionStringLoader : IConnectionStringLoader
{
}
它只有一个实现:
public class ConnectionStringLoader : IDbConnectionStringLoader, IMetaDataConnectionStringLoader
{
private readonly string _connectionStringName;
public ConnectionStringLoader(string connectionStringName)
{
_connectionStringName = connectionStringName;
}
public string Get()
{
var cs = ConfigurationManager.ConnectionStrings[_connectionStringName];
if (cs != null)
{
return cs.ConnectionString;
}
return null;
}
public void Write()
{
Console.WriteLine(_connectionStringName);
}
}
我的注册是这样的:
container.RegisterType<IMetaDataConnectionStringLoader, ConnectionStringLoader>(new InjectionConstructor("MetaConnection"));
container.RegisterType<IDbConnectionStringLoader, ConnectionStringLoader>(new InjectionConstructor("DbConnection"));
接口(interface)的要点是我可以在我的类中注入(inject)不同的接口(interface)并为每个实现获取正确的连接字符串。 但问题是无论最后完成什么注册都会覆盖之前的。
var foo = _container.Resolve<IDbConnectionStringLoader>();
var bar = _container.Resolve<IMetaDataConnectionStringLoader>();
foo.Write();
bar.Write();
输出是:
DbConnection
DbConnection
如果我颠倒注册顺序,输出将是 MetaConnection
两次。所以到目前为止我的结论是最后一次注册会覆盖之前的注册。但是,如果我将实现更改为派生类,它会起作用:
public class SomeOtherConnectionStringLoader : ConnectionStringLoader
{
public ConnectionStringLoaderImpl(string connectionStringName) : base(connectionStringName)
{
}
}
并更改注册:
container.RegisterType<IMetaDataConnectionStringLoader, ConnectionStringLoader>(new InjectionConstructor("MetaConnection"));
container.RegisterType<IDbConnectionStringLoader, SomeOtherConnectionStringLoader >(new InjectionConstructor("DbConnection"));
现在一切正常,但我不明白为什么。我尝试过不同的 lifetimemanagers,但结果相同。我原以为 Unity 会尝试根据接口(interface)使用“正确”的注入(inject)参数创建 ConnectionStringLoader
的实例,但这里似乎还有一些其他逻辑在起作用。
注册相互覆盖的原因有什么建议吗?
最佳答案
老实说,您使用接口(interface)的方式对我来说很奇怪,因为有两个接口(interface)仅由同一个类实现。我会发现更自然地遵循使用注册名称的下一种方法:
// If it is a loader the Write method makes no sense (IConnectionStringRepository?)
public interface IConnectionStringLoader
{
string Get();
void Write();
}
public class ConnectionStringLoader : IConnectionStringLoader
{
private readonly string _connectionStringName;
public ConnectionStringLoader(string connectionStringName)
{
_connectionStringName = connectionStringName;
}
public string Get()
{
var cs = ConfigurationManager.ConnectionStrings[_connectionStringName];
if (cs != null)
{
return cs.ConnectionString;
}
return null;
}
public void Write()
{
Console.WriteLine(_connectionStringName);
}
}
注册:
container.RegisterType<IConnectionStringLoader, ConnectionStringLoader>("Database", new InjectionConstructor("MetaConnection"));
container.RegisterType<IConnectionStringLoader, ConnectionStringLoader>("Metadata", new InjectionConstructor("DbConnection"));
决议:
var foo = _container.Resolve<IConnectionStringLoader>("Database");
var bar = _container.Resolve<IConnectionStringLoader>("Metadata");
foo.Write();
bar.Write();
关于c# - 统一注册相互覆盖,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36284738/