C# IOC-如何处理不断变化的依赖关系

C# IOC-如何处理不断变化的依赖关系,c#,dependency-injection,inversion-of-control,C#,Dependency Injection,Inversion Of Control,假设我们有以下服务类: PersonService.cs 公共类PersonService:IPersonService { 专用只读IPersonRepository\u存储库; 公共人员服务(IPerson存储库) { _存储库=存储库; } /*这里的接口成员*/ } 此服务类依赖于IPersonRepository。在我们的示例中,此存储库将处理文件连接: FilePersonRepository.cs 公共类FilePersonRepository:IPersonRepository

假设我们有以下服务类:

PersonService.cs
公共类PersonService:IPersonService
{
专用只读IPersonRepository\u存储库;
公共人员服务(IPerson存储库)
{
_存储库=存储库;
}
/*这里的接口成员*/
}
此服务类依赖于
IPersonRepository
。在我们的示例中,此存储库将处理文件连接:

FilePersonRepository.cs 公共类FilePersonRepository:IPersonRepository { 私有只读字符串\u文件路径; 公共FilePersonRepository(字符串文件路径) { _filePath=filePath; } /*这里的接口成员*/ } 此存储库取决于文件路径,该路径是确定应在此存储库中处理哪个文件所必需的

这些类连接在一个容器中:

publicstaticvoid配置容器(MyIocContainer容器)
{
容器寄存器(@“C:\temp\file.txt”);
container.Register();
container.Register();
}
现在,如果我使用静态路径(例如在配置文件中),那么一切都很好,它只被注入这个类构造函数一次

但是如果我有一个贯穿整个应用程序的
ViewModel
,而这个应用程序正在使用注册的服务类,会发生什么呢。并且必须通过打开文件夹对话框更改文件路径。如何处理

我认为在我的存储库中使用带有get/set的
属性
,或者创建一个引用
静态字符串
上路径的类,可能不太干净


有什么建议吗?

如何解决你的问题有很多解决方案,不可能说哪一个是最好的。但我非常确信,最佳实践是避免动态依赖性

我个人会这样做:

public interface IRepositoryConnectionString
{
    void SetConnectionString(string connectionString);
}

public interface IPersonRepository : IRepositoryConnectionString ...

public class FilePersonRepository : IPersonRepository
{
    /* file related private fields here */

    public FilePersonRepository ()
    {
        SetConnectionString(ConfigurationManager.ConnectionStrings[
            "FilePersonRepository.ConnectionString"]);
    }

    public SetConnectionString(string connectionString)
    {
         /* do all required stuf like flush previous file, open file, etc...  */ 
    }

    /* Interface members here... */
}
几乎每个存储都有某种类型的连接字符串,因此此接口应适用于大多数其他可能的实现(Mongo、SQL、Azure Table)

应用程序引导程序可以指定要使用的配置对话框。例如:

container.Register<IPersonRepositoryConfigurationDailog, FileRepositoryConfigurationDialog>();
container.Register();

创建并注册一个工厂,该工厂返回一个IPersonRepository,并具有一个接受路径的Create方法?此类运行时数据应该作为方法的参数传入,而不是通过构造函数传入。但是如果我也有一个
SqlPersonRepository
,它也实现了
IPersonRepository
(为了使此服务更灵活)整个签名将被弄乱。一旦抽象,您将拥有一个factory类,该类将根据配置文件设置输出正确的实现,请看一看。策略模式可能适用于此场景,但前提是您确定在运行时不需要更改文件路径。
container.Register<IPersonRepositoryConfigurationDailog, FileRepositoryConfigurationDialog>();