我们正在开发Windows服务,我想在存储库中动态更改dbcontext
类。
我有三个db上下文类
public abstract class Context : DbContext, IUnitOfWork
{
protected Context(string connectionString) : base(connectionString)
{
}
}
public class PlatformContext : Context
{
private readonly string _connectionString;
public PlatformContext(string connectionString)
: base(connectionString)
{
_connectionString = connectionString;
}
}
public class PlatformReplicaContext : Context
{
private readonly string _connectionString;
public PlatformReplicaContext(string connectionString)
: base(connectionString)
{
_connectionString = connectionString;
}
}
public class TempContext : Context
{
private readonly string _connectionString;
public TempContext(string connectionString)
: base(connectionString)
{
_connectionString = connectionString;
}
}
我有资源库
public interface ICategoryRepository : IRepository<Category>
{
}
public class CategoryRepository :Repository<Category>, ICategoryRepository
{
public CategoryRepository(Context context) : base(context)
{
}
}
因此我使用CQRS我还有另外三个类
public class CategoryBasicQuery:IRequest<BaseQueryResponse>
{
public int CategoryId { get; set; }
}
public class CategoryBasicQueryHandler : IRequestHandler<CategoryBasicQuery, BaseQueryResponse>
{
private readonly ICategoryRepository _categoryRepository;
private readonly IMapper _mapper;
public CategoryBasicQueryHandler(ICategoryRepository categoryRepository, IMapper mapper)
{
_categoryRepository = categoryRepository;
_mapper = mapper;
}
public async Task<BaseQueryResponse> Handle(CategoryBasicQuery request, CancellationToken cancellationToken)
{
var entry = await _categoryRepository.FindAsync(request.CategoryId);
if (entry == null)
{
return new NotFoundResponse();
}
var response = _mapper.Map<CategoryBasicResponse>(entry);
return response;
}
}
现在问题是
此类别存储库应该能够在所有3种类型的上下文中执行查询。 但是如何在使用autofac时注册类? 然后我想出了一个在运行时生成存储库的解决方案,如下所示
public class RepositoryFactory
{
public static TRepository GetRepositoryInstance<T, TRepository>(
params object[] args)
where TRepository : IRepository<T>
{
return (TRepository)Activator.CreateInstance(typeof(TRepository), args);
}
}
我在CategoryBasicQueryHandler
类中调用此方法,就像这样
var categoryRepo = RepositoryFactory.GetRepositoryInstance<Category, CategoryRepository>(new PlatformReplicaContext("connectionString"));
但是从CQRS打电话
var categoty = new Category();
var command = new CategoryBasicQuery {CategoryId = categoryId};
var result = _mediator.Send(command);
VS给我以下错误
我的autofac注册如下
builder.RegisterType<CategoryService>().AsSelf();
builder.RegisterType<ActionRepository>().As<IActionRepository>();
builder.RegisterType<CategoryRepository>().As<ICategoryRepository>();
builder.RegisterType<Mapper>().As<IMapper>();
任何人都可以帮我解决这个问题,或者提出一个好的方法来处理这种情况。
感谢。
答案 0 :(得分:1)
这可能为您提供可行解决方案的良好起点:http://autofaccn.readthedocs.io/en/latest/resolve/relationships.html#keyed-service-lookup-iindex-x-b
builder.RegisterType<PlatformContext>().Keyed<Context>("platform");
builder.RegisterType<PlatformReplicaContext>().Keyed<Context>("replica");
builder.RegisterType<TempContext>().Keyed<Context>("temp");
您在评论中提到某个名为action
的变量将指示要使用的实现:
public class Class1
{
private readonly IIndex<string, Context> contexts;
public Class1(IIndex<string, Context> contexts)
{
this.contexts = contexts;
}
public void Whatever()
{
string action = ...; // platform, replica or temp
Context context = this.contexts[action];
...
}
}
当然,这需要进行调整,以使其适合您的应用程序设计的其余部分。一个可能的例子可能是:
Context context = this.contexts[action];
using(ILifetimeScope scope = container.BeginLifetimeScope(builder =>
{
builder.RegisterInstance(context).As<Context>();
}))
{
// Because we are resolving IMediator from the scope, the selected Context will be used in all dependencies
var mediator = scope.Resolve<IMediator>();
mediator.Send(...);
}