在Autofac中为一个接口使用不同的实现

时间:2018-09-12 07:00:19

标签: c# autofac quartz

我要执行以下操作。

我用Quartz.Net实现了一个调度程序,对于IOC,我使用Autofac。 现在,我想多次启动一个作业,但是每个作业的数据库都不同。我的存储库采用一个参数,该参数包装了我的连接字符串。 参数的类型为IOptions<T>,并注入到存储库的构造函数中。该存储库也被注入到不同的服务中。

问题是,我无法直接访问存储库,因为涉及的服务很多,它们都使用同一存储库。

该存储库由其他人实现,它包含多个查询和一个连接字符串属性。我为不同的国家(销售系统)使用不同的数据库,但是它们都是相同的,所以我只有一个用于所有数据库的存储库。

从JSON文件读取连接字符串:

{
  "PriceListSettings": [
    {
      "Country": "DE",
      "ConnectionString": "Initial Catalog=Catalog_DE;Data Source=.\\SQLEXPRESS;Integrated Security=true;",
      "ExecutionTime": "0 0 0 1/1 * ? *"
    },
    {
      "Country": "AT",
      "ConnectionString": "Initial Catalog=Catalog_AT;Data Source=.\\SQLEXPRESS;Integrated Security=true;",
      "ExecutionTime": "0 0 0 1/1 * ? *"
    }
  ]
}

我希望每个工作都有一个作用域,以便可以注入或设置其他连接字符串。

使用Quarz可以设置触发器。问题在于,这些作业都是在可配置的时间开始的,并且应每晚执行一次。但是我不知道确切的时间。

我尝试使用

using (var scope = Program.Container.BeginLifetimeScope())
{
    //Does not seem to work this way
    //var repo = scope.Resolve<IRepository>();
    //repo.PricelistServiceConfig = priceListConfig;            
}

我也试图让Quartz在单线程中运行,但看来我无法正确设置仓库的属性。

使用的框架:

  • .Net Framework 4.6(无法升级)
  • Autofac 4.8.1
  • Autofac.Extras.Quartz 4.2.0
  • 石英3.0.6

1 个答案:

答案 0 :(得分:0)

看来,您差不多明白了。我不知道您的类到底是什么样子,因此我为JobReposiroty和服务类提供了一些存根实现示例。有一项工作需要向建设者提供两项服务。两种服务都需要将存储库作为其构造函数的参数:

[Test]
public void AutofacLifetimeScope()
{
    // Arrange
    var builder = new ContainerBuilder();
    builder.RegisterType<Job>();
    builder.RegisterType<AnotherService>();
    builder.RegisterType<SomeService>();
    builder.RegisterType<Repository>().InstancePerLifetimeScope().WithProperty(ResolvedParameter.ForKeyed<Option>("opt"));

    var container = builder.Build();

    // Act
    Job job1;
    var option1 = new Option {ConnectinString = "DE Connection"};
    using (var scope = container.BeginLifetimeScope(c => c.RegisterInstance(option1).Keyed<Option>("opt")))
    {
        job1 = scope.Resolve<Job>();
    }

    Job job2;
    var option2 = new Option { ConnectinString = "AT Connection" };
    using (var scope = container.BeginLifetimeScope(c => c.RegisterInstance(option2).Keyed<Option>("opt")))
    {
        job2 = scope.Resolve<Job>();
    }

    //Assert
    Assert.AreEqual(job1.SomeService.Repository.PriceListConfig, option1);
    Assert.AreEqual(job1.AnotherService.Repository.PriceListConfig, option1);

    Assert.AreEqual(job2.SomeService.Repository.PriceListConfig, option2);
    Assert.AreEqual(job2.AnotherService.Repository.PriceListConfig, option2);
}

public class Repository
{
    public Option PriceListConfig { get; set; }
}

public class Option
{
    public string ConnectinString { get; set; }
    public string Country { get; set; }
    public string ExecutionTime { get; set; }
}

public class Job
{
    public SomeService SomeService { get; }
    public AnotherService AnotherService { get; }

    public Job(SomeService someService, AnotherService anotherService)
    {
        SomeService = someService;
        AnotherService = anotherService;
    }
}

public class AnotherService
{
    public Repository Repository { get; }

    public AnotherService(Repository repository)
    {
        Repository = repository;
    }
}

public class SomeService
{
    public Repository Repository { get; }

    public SomeService(Repository repository)
    {
        Repository = repository;
    }
}

主要思想是为每个生存期范围注册Repository并进行属性注入,这将在以后创建生存期范围时进行配置。我通过公共属性提供了注入实例。仅用于示例的简单测试。希望对您有所帮助。