Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/314.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 如何在使用Unity创建实现给定接口的类的实例时设置给定属性_C#_Dependency Injection_Unity Container - Fatal编程技术网

C# 如何在使用Unity创建实现给定接口的类的实例时设置给定属性

C# 如何在使用Unity创建实现给定接口的类的实例时设置给定属性,c#,dependency-injection,unity-container,C#,Dependency Injection,Unity Container,鉴于这种简化的情况: public interface IRepository { string ConnectionString { get; set; } } public abstract class Repository : IRepository { public string ConnectionString { get; set; } } public class CustomerRepository : Repository, ICustomerReposit

鉴于这种简化的情况:

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
{
}
以及以下统一注册:

IUnityContainer container = new UnityContainer();
container.RegisterType<ICustomerRepository, CustomerRepository>();
container.RegisterType<IOrderRepository, OrderRepository>();
IUnityContainer container=newunitycontainer();
container.RegisterType();
container.RegisterType();
为了设置ConnectionString属性(以及扩展任何其他属性)的值,建议以何种方式拦截任何IRepository实例的创建


更新1:这篇文章不是关于设计模式或涉及对原始类进行重新分解的替代解决方案。这是关于Unity的,也是通过拦截实现给定接口的实例的创建来设置属性的最佳方法。

如果将
connectionString
设置为构造函数参数,则配置如下所示

container.RegisterType<ICustomerRepository, CustomerRepository>(new InjectionConstructor("myConnStr1");
container.RegisterType(新注入构造函数(“myConnStr1”);
对于属性注入,配置为

container.RegisterType<IOrderRepository, OrderRepository>(new InjectionProperty("ConnectionString", "myConnStr2");
container.RegisterType(新的InjectionProperty(“ConnectionString”、“myConnStr2”);

[更新] 包含Castle Windsor的端口。它允许您注册接受参数的工厂接口

public interface ICustomerRepositoryFactory
{
  ICustomerRepository Create(string connectionString);
}

container.RegisterType<ICustomerRepositoryFactory>(new TypedFactory());
container.RegisterType<ICustomerRepository, CustomerRepository>(new InjectionProperty("ConnectionString");
公共接口ICCustomerRepositoryFactory
{
ICCustomerRepository创建(字符串连接字符串);
}
RegisterType(新的TypedFactory());
RegisterType(新的InjectionProperty(“ConnectionString”);

如果解析工厂接口并调用
Create
方法,它将把方法参数映射到相应的构造函数参数。[Update2]它还不支持属性注入(还没有。明天再问)。它还支持属性注入,但在注册存储库类型时,您必须将属性标记为注入。[/Update2]您不必实现工厂。扩展可以为您实现此功能。

因为您需要来自不同提供程序的连接字符串(如您在评论中所述)。我建议对设计稍作修改,您可以添加一个新的依赖项,例如
IConnectionStringProvider

public interface IConnectionStringProvider 
{
    string GetConnectionString(); 
}
然后更新
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(); 
                 }
            }
   }    
然后,您可以根据需要使用unity注入正确的连接字符串提供程序

container.RegisterType<IConnectionStringProvider , ConnectionStringProvider>();
container.RegisterType();

您的存储库不应负责创建连接

  • 你违反了单一责任原则
  • 您得到了重复的代码=将来更难维护代码
  • 如果要在存储库之间共享连接,您会怎么做
  • 解决方案:

    创建一个
    IConnectionFactory
    (您可以将该实现注册为实例/单例),并将其用作存储库中的依赖项

    更新1

    您可以使用
    InjectionProperty
    。在配置连接字符串之前,请在该行中查找该字符串

    更新2:

    使用工厂配置存储库:

    比如:

    container.Configure<IStaticFactoryConfiguration>()
        .RegisterFactory<ICustomerRepository>
        (new FactoryDelegate(c => 
           { 
              var repos = new CustomerRepository();
              repos.ConnectionString = yourComPlus.ConnectionString;
              return repos;
           }
        ));
    
    container.Configure()
    .注册工厂
    (新FactoryDelegate(c=>
    { 
    var repos=new CustomerRepository();
    repos.ConnectionString=yourComPlus.ConnectionString;
    回购回报;
    }
    ));
    
    如果您有不同的存储库,这意味着每个存储库都有不同的连接字符串,这是否正确?@SofianHnaide:是的,每个存储库可能有不同的连接字符串。现在在我的特定情况下,只有连接字符串,但解决连接字符串的方法会随着环境的变化而变化,例如,在开发中pment来自web.config,在生产中来自与COM对象的交互操作。这是一个非常好的解决方法,但让我们假设一下,我不能按照您的建议修改原始类并将参数添加到构造函数中。我想知道如何使用截取“捕获”任何实现IRepository的实例,并设置ConnectionString属性。还要注意,连接字符串的实际值只有在运行时才知道,因此解决方案必须考虑到这一点。如果我从头开始建模此问题,我将使用使用构造函数注入的IConnectionStringProvider,但假设我无法修改它他创建了原始类/接口,并试图从AOP的角度解决问题。如何在创建实例之后但在使用实例之前设置属性?那么您应该跟踪(列表)我同意你的观点,这不是最好的设计,但是让我们假设这是你所拥有的,并且是不能改变的。问题更多的是关于统一本身,而不是关于设计模式。然后你需要使用
    InjectionProperty
    你介意添加吗一些代码解释了如何使用InjectionProperty解决问题?请记住,原始类/接口无法修改。如果我只需要一个静态字符串,InjectionProperty可能会工作,但正如前面所解释的,我需要在运行时执行一些代码以查找实际值,例如连接字符串有时是res通过使用COM对象解决。@jgauffin据我所知,
    StaticFactoryExtension
    被弃用,取而代之的是
    InjectionFactory
    [过时(“使用RegisterType(new InjectionFactory(…)代替扩展的方法。”)]