Azure 表和 EntityFrameworkCore InMemoryDb 的 Autofac 依赖注入

问题描述 投票:0回答:1

我构建了一个与 Azure 表存储表和 EntityFrameworkCore InMemory 数据库通信的服务类。

public sealed class NotificationService : INotificationService
{
    private readonly NotificationDatabaseContext _inMemoryCache;
    private readonly INotificationRepository _notificationRepository;

    public NotificationService(
        NotificationDatabaseContext inMemoryCache,
        INotificationRepository notificationRepository)
    {
        _inMemoryCache = inMemoryCache;
        _notificationRepository = notificationRepository;
    }

    public string Test()
    {
        return DateTime.UtcNow.ToShortTimeString();
    }
}

public sealed class NotificationRepository : INotificationRepository
{
    private readonly CloudTable _cloudTable;

    public NotificationRepository(CloudTable cloudTable)
    {
        _cloudTable = cloudTable;
    }
}

public class NotificationDatabaseContext : DbContext
{
    public NotificationDatabaseContext(DbContextOptions<NotificationDatabaseContext> dbContextOptions) : base(dbContextOptions) { }
    public DbSet<Notification> Notifications { get; set; }

    protected override void OnModelCreating(ModelBuilder modelBuilder)
    {
        modelBuilder.Entity<Notification>()
            .HasKey(x => x.RowKey);
    }
}

public sealed class Notification : TableEntity
{
    public bool HasBeenRead { get; set; }
}

我正在使用 Autofac 进行依赖注入。

public sealed class AutofacAzureTableStorageModule : AutofacAzureModuleBase
{
    private static string _azureStorageConnectionString;
    private const string NOTIFICATIONS_AZURE_TABLE_STORAGE_CLOUD_TABLE_NAME = "Notifications";

    public AutofacAzureTableStorageModule(string azureStorageConnectionString)
    {
        _azureStorageConnectionString = azureStorageConnectionString;
    }

    protected override void Load(ContainerBuilder containerBuilder)
    {
        ConfigureAzureStorageAccount(containerBuilder, _azureStorageConnectionString);
        ConfigureServicesWithRepositories(containerBuilder);
        ConfigureAzureCloudTables(containerBuilder);
        ConfigureCloudTablesForRepositories(containerBuilder);
    }

    private static void ConfigureServicesWithRepositories(ContainerBuilder containerBuilder)
    {
        containerBuilder.RegisterType<NotificationService>()
                .AsImplementedInterfaces()
                .InstancePerLifetimeScope();
    }

    private static void ConfigureAzureCloudTables(ContainerBuilder containerBuilder)
    {
        containerBuilder.Register(x => x.Resolve<CloudStorageAccount>().CreateCloudTableClient());

        containerBuilder.Register(x =>
                GetCloudTable(x, NOTIFICATIONS_AZURE_TABLE_STORAGE_CLOUD_TABLE_NAME))
                .Named<CloudTable>(NOTIFICATIONS_AZURE_TABLE_STORAGE_CLOUD_TABLE_NAME);
    }

    private static void ConfigureCloudTablesForRepositories(ContainerBuilder containerBuilder)
    {
        containerBuilder.RegisterType<NotificationRepository>()
                .WithParameter(
                (x, y) => x.ParameterType == (typeof(CloudTable)),
                (x, y) => y.ResolveNamed<CloudTable>(
                NOTIFICATIONS_AZURE_TABLE_STORAGE_CLOUD_TABLE_NAME))
                .AsImplementedInterfaces();
    }
}

public abstract class AutofacAzureModuleBase : Module
{
    protected static void ConfigureAzureStorageAccount(ContainerBuilder containerBuilder, string azureStorageConnectionString)
    {
        containerBuilder.Register(c => CreateAzureCloudStorageAccount(azureStorageConnectionString));
    }

    private static CloudStorageAccount CreateAzureCloudStorageAccount(string azureStorageConnectionString)
    {
        if (String.IsNullOrEmpty(azureStorageConnectionString))
        {
            throw new Exception("Azure Storage connection string is null!");
        }

        return CloudStorageAccount.Parse(azureStorageConnectionString);
    }

    protected static CloudTable GetCloudTable(IComponentContext componentContext, string tableName)
    {
        var cloudTable = componentContext.Resolve<CloudTableClient>().GetTableReference(tableName);

        cloudTable.CreateIfNotExistsAsync().GetAwaiter();

        return cloudTable;
    }
}

所有内容都在 Program.cs 文件中配置,如下所示:

// Add services to the container.
builder.Services.AddControllersWithViews();

// Configure EntityFrameworkCore InMemoryDatabase Cache
var notificationsInMemoryDatabaseName = builder.Configuration["EntityFrameworkCoreInMemoryDatabase:NotificationsDatabaseName"];
builder.Services.AddDbContext<NotificationDatabaseContext>(options =>
    options.UseInMemoryDatabase(notificationsInMemoryDatabaseName));
// Configure EntityFrameworkCore InMemoryDatabase Cache

// Configure Autofac Modules
var azureStorageConnectionString = builder.Configuration["AzureStorage"];
builder.Host.UseServiceProviderFactory(new AutofacServiceProviderFactory());
// Register services directly with Autofac here.
builder.Host.ConfigureContainer<ContainerBuilder>(builder =>
{
    builder.RegisterModule(new AutofacAzureTableStorageModule(azureStorageConnectionString));
});
// Configure Autofac Modules

var app = builder.Build();

Autofac 依赖注入不正确(之前当我只是将 DI 用于 Azure 存储表(没有 EntityFrameworkCore InMemory 数据库)时它就可以工作)。

请有人建议/帮助我重构 Autofac 依赖注入,以与 InMemory 数据库一起使用?

更新:

抛出以下异常:

c# asp.net-core entity-framework-core autofac in-memory-database
1个回答
0
投票

我已经通过将以下方法添加到 Autofac 模块来修复它。

private static void ConfigureEntityFrameworkCore(ContainerBuilder containerBuilder)
{
    containerBuilder.Register(c => new DbContextOptionsBuilder<NotificationDatabaseContext>()
        .UseInMemoryDatabase(_entityFrameworkCoreInMemoryDatabaseNameForNotifications)
        .Options)
        .SingleInstance();

    containerBuilder.RegisterType<NotificationDatabaseContext>()
        .WithParameter(
            (x, y) => x.ParameterType == typeof(DbContextOptions<NotificationDatabaseContext>),
            (x, y) => y.Resolve<DbContextOptions<NotificationDatabaseContext>>())
        .InstancePerLifetimeScope();
}

希望这对将来的人有帮助。

© www.soinside.com 2019 - 2024. All rights reserved.