使用 Autofac ASP.Net Core 5 注册动态通用存储库

Registering dynamic generic repository with Autofac ASP.Net Core 5

我正在尝试创建一个包装器存储库,它将能够使用基于类型的通用存储库。

到目前为止我有:

启动:

builder.RegisterAssemblyTypes(Assembly.Load("Data"))
               .Where(t => t.Namespace.Contains("Repositories"))
               .As(t => t.GetInterfaces().FirstOrDefault(i => i.Name == "I" + t.Name))
               .InstancePerLifetimeScope();

builder.RegisterType<GenericRepositoryLong<EventRegistrationActivity>>()
            .As<IGenericRepositoryLong<ILongEntity>>()
            .Keyed<IGenericRepositoryLong<ILongEntity>>(ActivityType.EventRegistration)
            .AsSelf()
            .InstancePerLifetimeScope();

builder.Register<Func<ActivityType, IGenericRepositoryLong<ILongEntity>>>(c =>
{
    var componentContext = c.Resolve<IComponentContext>();
    return (activityType) =>
    {
        var repo = componentContext.ResolveKeyed<IGenericRepositoryLong<ILongEntity>>(activityType);
        return repo;
    };
});

ActivityRepository 基本上是一个处理缓存数据一致性的包装存储库。它还应该使用通用存储库来保存实体。通用存储库在注入时运行良好,但在我尝试以下操作时它不起作用:

public class ActivityRepository: IActivityRepository
{
    private readonly Func<ActivityType, IGenericRepositoryLong<ILongEntity>> ActivityRepoFac;

    public ActivityRepository(Func<ActivityType, IGenericRepositoryLong<ILongEntity>> activityRepoFac)
    {
        ActivityRepoFac = activityRepoFac;
    }

    public async Task CreateActivityAsync(IFeedActivity activity, ActivityType activityType)
    {
        var repo = ActivityRepoFac(activityType);
        ...repo code here
    }
}

ActivityType 是一个简单的 enum,我得到的错误是:

The type
'Infra.DataProvider.GenericRepositoryLong`1[Domain.Entities.Activities.EventRegistrationActivity]'
is not assignable to service
'Infra.DataProvider.IGenericRepositoryLong`1[[Domain.ILongEntity, Domain, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]]'.

我正在尝试做的事情是否可行,如果可行,我是否遗漏了什么? 另外,这是一个好习惯吗?

如有任何帮助,我们将不胜感激。

这里没有足够的内容来果断地说出发生了什么,但例外情况很能说明问题。

这里的注册是您需要测试的重要部分,甚至没有所有的键控和额外设置。就是这样:

builder.RegisterType<GenericRepositoryLong<EventRegistrationActivity>>()
       .As<IGenericRepositoryLong<ILongEntity>>();

异常是说你不能将 GenericRepositoryLong<EventRegistrationActivity> 转换为 IGenericRepositoryLong<ILongEntity>

换句话说,如果你这样做,它不会编译:

IGenericRepositoryLong<ILongEntity> repo =
  new GenericRepositoryLong<EventRegistrationActivity>();

我实际上没有看到 GenericRepositoryLong<T>IGenericRepositoryLong<T> 实体的定义,所以我不能肯定地说,但这就是例外情况。

通常这是因为接口是这样声明的:

public interface IGenericRepositoryLong<T>

并且它缺少 proper variance keyword 表示您要执行的操作。我猜你可能想要

public interface IGenericRepositoryLong<out T>

我会尝试在完全不涉及 Autofac 的单元测试中对此进行故障排除。如果您要手动创建所有类型和属性并自己连接它们,它是否可行?试图弄清楚 同时 还尝试注册事物并排列 Autofac 语法可能会导致混淆,例如“是 Autofac 这样做,还是我的代码中有什么?”

最后,与问题无关,我确实注意到您同时注册了 AsSelfKeyed,这看起来很奇怪。我的意思是,您实际上可能希望 能够直接解析 GenericRepositoryLong<T>,但考虑到您所展示的设置以及它与 activity 的紧密耦合输入,您可能 想要它。拥有它不会 伤害 任何东西,但如果您不小心解决了一些您不打算解决的问题,这仅仅是因为您添加了太多 services/registrations,它也会导致混乱。