[英]Implementing “Repository Rotator” factory
I have .Net Core Web API application. 我有.Net Core Web API应用程序。 There is some Get method in controller and injected IRepositoryProviderFactory.
控制器中有一些Get方法,并注入了IRepositoryProviderFactory。 Nothing special.
没什么特别的。
[ApiController]
public class DataController : ControllerBase
{
private readonly ILogger<DataController> _logger;
private readonly IRepositoryProviderFactory _repositoryProviderFactory;
#region ctor
/// <summary>
/// ctor
/// </summary>
public DataController(ILogger<DataController> logger, IRepositoryProviderFactory repositoryProviderFactory)
{
_logger = logger;
_repositoryProviderFactory = repositoryProviderFactory;
}
[HttpPost]
public async Task<IActionResult> GetData([FromBody] SearchModel model)
{
if (!ModelState.IsValid)
{
return BadRequest(ModelState);
}
try
{
var data = await _repositoryProviderFactory.GetDataAsync(model);
return Ok(data);
}
catch (Exception ex)
{
return StatusCode((int)HttpStatusCode.InternalServerError);
}
}
}
There are repositories based on the same Interface to get data from different data sources. 存在基于相同接口的存储库以从不同数据源获取数据。
public Repository1: IDataRepository {}
public Repository2: IDataRepository {}
public Repository3: IDataRepository {}
I'm using DI so all parts are registered in services as Scoped or Transients. 我正在使用DI,因此所有部件都在服务中注册为Scoped或Transients。 Some repositories are using EntityFramework.
一些存储库正在使用EntityFramework。
services.AddScoped<IDataRepository, Repository1>();
services.AddScoped<IDataRepository, Repository2>();
services.AddScoped<IDataRepository, Repository3>();
Ok, now I need to implement RepositoryProviderFactory to return repository. 好的,现在我需要实现RepositoryProviderFactory来返回存储库。 But there is one required functionality: it must return for every call different repository .
但是有一个必需的功能: 它必须为每个调用不同的存储库返回 。
I have injected IEnumerable and I need to return Repository1, Repository2, Repository3 and again Repository1, … etc. So all repositores are used the same time. 我注入了IEnumerable,我需要返回Repository1,Repository2,Repository3和Repository1,...等等。所以所有的存储库都是同时使用的。
/// <summary>
/// ctor
/// </summary>
public RepositoryProviderFactory(
ILogger<RepositoryProviderFactory> logger,
IEnumerable<IDataRepository> dataRepositories)
{
_logger = logger;
_dataRepositories = dataRepositories;
}
public IDataRepository GetRepository()
{
// TODO: Logic to cycle repositories
var instance = dataRepositories.Where();
return instance;
}
How to do this? 这个怎么做?
Factory can't be registered as Singleton, because repositories have another dependencies that have Scoped Lifetime (DbContext etc.) Factory无法注册为Singleton,因为存储库具有另一个具有Scoped Lifetime的依赖项(DbContext等)
How can I create some thread safe singleton object to be able persists last used repository and serve another one, for another call? 如何创建一些线程安全的单例对象,以便能够持久保存最后使用的存储库并为另一个存储库提供服务,以进行另一个调用?
Well, I did it this way. 嗯,我是这样做的。
I made class GlobalAppData and registered is as Singleton. 我创建了类GlobalAppData并注册为Singleton。
services.AddSingleton<GlobalAppData>();
Then I made simple implementation (not finished yet). 然后我做了简单的实现(还没有完成)。
public class GlobalAppData
{
private IDataRepository[] _availableRepositories;
private IDataRepository_lastUsedRepository;
/// <summary>
/// ctor
/// </summary>
public GlobalAppData()
{
_availableRepositories = new IDataRepository[0];
}
public void TryRegisterRepositories(IEnumerable<IDataRepository> repositories)
{
if (_availableRepositories.Length > 0)
{
return;
}
_availableRepositories = repositories.ToArray();
_lastUsedRepository = null;
}
public IDataRepository GetNextRepository()
{
if (_lastUsedRepository == null)
{
_lastUsedRepository = _availableRepositories[0];
return _lastUsedRepository;
}
var lastUsedIndex = _availableRepositories.IndexOf(_lastUsedRepository);
if (lastUsedIndex < _availableRepositories.Length - 1)
{
lastUsedIndex++;
}
else
{
lastUsedIndex = 0;
}
_lastUsedRepository = _availableRepositories[lastUsedIndex];
return _lastUsedRepository;
}
}
Then because of DI there will be stored original instances, not injected ones, I made just simple compare in factory. 然后因为DI会存储原始实例,而不是注入的实例,我在工厂里做了简单的比较。
var instanceData = _globalAppData.GetNextRepository();
var instance = _repositories.SingleOrDefault(r => r.GetType() == instanceData.GetType());
Not perfect, but it works as a start. 不完美,但它起初作用。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.