[英]How to set a given property when an instance of a class which implements a given interface is created using Unity
Given this simplified scenario: 在这种简化的情况下:
public interface IRepository
{
string ConnectionString { get; set; }
}
public abstract class Repository : IRepository
{
public string ConnectionString { get; set; }
}
public class CustomerRepository : Repository, ICustomerRepository
{
}
public class OrderRepository : Repository, IOrderRepository
{
}
and the following Unity registrations: 以及以下Unity注册:
IUnityContainer container = new UnityContainer();
container.RegisterType<ICustomerRepository, CustomerRepository>();
container.RegisterType<IOrderRepository, OrderRepository>();
What is the recommended way to intercept the creation of any IRepository instance in order to set the value for the ConnectionString property (and by extension any other property). 为了设置ConnectionString属性的值(以及扩展为其他属性的值),建议什么方法来拦截任何IRepository实例的创建。
UPDATE 1: This post is not about design patters or an alternate solution involving re-factoring of the original classes. 更新1:这篇文章与设计模式或涉及重构原始类的替代解决方案无关。 It's about Unity and the best way to set a property by intercepting the creation of instances implementing a given interface. 这是关于Unity以及通过拦截实现给定接口的实例的创建来设置属性的最佳方法。
If you make the connectionString
a constructor parameter the configuration looks like this 如果将connectionString
用作构造函数参数,则配置如下所示
container.RegisterType<ICustomerRepository, CustomerRepository>(new InjectionConstructor("myConnStr1");
For property injection the configuration is 对于属性注入,配置为
container.RegisterType<IOrderRepository, OrderRepository>(new InjectionProperty("ConnectionString", "myConnStr2");
[Update] The TecX project on codeplex contains a port of the Castle Windsor Typed Factory Facilities . [更新] Codeplex上的TecX项目包含温莎城堡类型工厂设施的端口。 It allows you to register a factory interface that takes parameters. 它允许您注册带有参数的工厂接口。
public interface ICustomerRepositoryFactory
{
ICustomerRepository Create(string connectionString);
}
container.RegisterType<ICustomerRepositoryFactory>(new TypedFactory());
container.RegisterType<ICustomerRepository, CustomerRepository>(new InjectionProperty("ConnectionString");
If you resolve the factory interface and call the Create
method it will map the method parameter to the according constructor parameter. 如果解析工厂接口并调用Create
方法,它将把方法参数映射到相应的构造函数参数。 [Update2]
It does not yet support property injection (yet. ask again tomorrow)
. [Update2]
它尚不支持属性注入(但请明天再问)
。 It also supports property injection but you will have to mark the property for injection when you register your repository types. 它还支持属性注入,但是在注册存储库类型时,您将必须标记要注入的属性。 [/Update2] You will not have to implement the factory. [/ Update2]您不必实现工厂。 The extension does that for you. 该扩展程序可以为您完成此任务。
Since you need connection strings coming from differnt providers (as you mentioned in your comment). 由于您需要来自不同提供商的连接字符串(如您在评论中所述)。 I would suggest a slight change to the design, you can add a new dependency such as IConnectionStringProvider
我建议对设计进行一些更改,您可以添加一个新的依赖项,例如IConnectionStringProvider
public interface IConnectionStringProvider
{
string GetConnectionString();
}
Then update IRepository
然后更新IRepository
public interface IRepository
{
IConnectionStringProvider ConnectionStringProvider {get; set;}
string ConnectionString { get; } // no set is required
}
public abstract class Repository : IRepository
{
IConnectionStringProvider ConnectionStringProvider {get; set;}
public string ConnectionString
{
get
{
return ConnectionStringProvider.GetConnectionString();
}
}
}
Then you can use unity to inject the right connection string provider per your need 然后,您可以根据需要使用unity注入正确的连接字符串提供程序
container.RegisterType<IConnectionStringProvider , ConnectionStringProvider>();
Your repositories should not be responsible of creating the connection. 您的存储库不应该负责创建连接。
Solution: 解:
Create an IConnectionFactory
(which implementation you can register as an instance/singleton) and use that as an dependency in your repositories. 创建一个IConnectionFactory
(可以将其注册为实例/单例实现),并将其用作存储库中的依赖项。
Update 1 更新1
You can use InjectionProperty
. 您可以使用InjectionProperty
。 Lookup the connection string on the line before you configure it. 在配置之前,先在行上查找连接字符串。
Update 2: 更新2:
Use factories to configure the repositories: http://www.pnpguidance.net/post/RegisteringFactoryMethodCreateObjectsUnityStaticFactoryExtension.aspx 使用工厂来配置存储库: http : //www.pnpguidance.net/post/RegisteringFactoryMethodCreateObjectsUnityStaticFactoryExtension.aspx
Something like: 就像是:
container.Configure<IStaticFactoryConfiguration>()
.RegisterFactory<ICustomerRepository>
(new FactoryDelegate(c =>
{
var repos = new CustomerRepository();
repos.ConnectionString = yourComPlus.ConnectionString;
return repos;
}
));
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.