Autofac – 扫描和批量注册泛型类型



在我的项目中,我的所有存储库都有以下基类:

public abstract class RepositoryBase<TContext, TEntity> : Disposable, IRepository<TEntity>
        where TEntity : class
        where TContext : DbContext, new()
    {...}

从基类继承的存储库未指定数据库上下文类型(因为上下文对于所有应用程序都不相同):

public class UserRepository<TContext> : RepositoryBase<TContext, User>
    where TContext : BaseContext, new()
{
    public UserRepository( IDatabaseFactory<TContext> databaseFactory, ILoggerFactory loggerFactory )
        : base( databaseFactory, loggerFactory )
    {...}
}
public class ProductRepository<TContext> : RepositoryBase<TContext, Product>
    where TContext : BaseContext, new()
{...}

我知道 autofac 能够注册符合以下标准的所有类型:

builder.RegisterAssemblyTypes( assembly )
    .Where(...)
    .AsImplementedInterfaces();

有没有办法对从特定上下文的 RepositoryBase 继承的所有类型执行相同的操作?像这样:

public class MyContext : BaseContext { }
builder.RegisterAssemblyTypes( assembly )
    .Where(...)
    .AsImplementedInterfaces(/*specify  MyContext as TContext*/);

TContext 是否以继承自 RepositoryBase 的类型而闻名?如果您知道UserRepository将使用MyContext,而ProductRepository将使用MyOtherContext,则可以这样定义它们,并让Autofac自动拾取它们:

public class UserRepository : RepositoryBase<MyContext, User>
{...}
public class ProductRepository : RepositoryBase<MyOtherContext, Product>
{...}

否则,我假设您有允许来自多个上下文的数据的要求?

public class MyContextUserRepository : RepositoryBase<MyContext, User>
{...}
public class MyOtherContextUserRepository : RepositoryBase<MyOtherContext, User>
{...}

在这种情况下,您可以按上述方式定义它们,但在解决时,您必须在该特定场景中传递所需的上下文

public class MyClass
{
    readonly IRepository<User> _userRepository;
    public MyClass(IRepository<User> userRepository)
    {
        _userRepository = userRepository;
    }
}
var myClass = _container.Resolve<MyClass>(
                new ResolvedParameter(
                    (x, y) => x.ParameterType == typeof (IRepository<User>),
                    (x, y) => y.Resolve<MyContextUserRepository>()));

或者,您可以在注册时执行此操作,在这种情况下,您可能会发现Autofac文档很有用。

评论后编辑

好的,您有多个应用程序共享一个包含接口、实现和实体的公共库。给定的应用程序可以定义其实现和实体,但只有一个特定于该应用程序的上下文。

// your application specific context
public class MySpecificApplicationContext : DbContext { }
// get your entity types that a given application uses
var entityTypes = GetEntityTypes();
// register a repository implementation for each entity type
// note RepositoryBase is not abstract for this example
for (var i = 0; i < entityTypes.Count; i++)
{
    var entityType = entityTypes[i];
    builder
        .RegisterType(typeof (RepositoryBase<,>)
        .MakeGenericType(typeof (MySpecificApplicationContext), entityType))
        .As(typeof (IRepository<>).MakeGenericType(entityType))
        .InstancePerLifetimeScope();
}
// resolve an entity repository
var userRepository = container.Resolve<IRepository<User>>();

最新更新