[英]How to realize explicit and implicit type conversion for non-generic synonyms of generic struct?
[英]How to realize a generic DI?
我有多個服務和多個存儲庫。 我所有的服務都包含一個存儲庫和一個映射器。 所以,我創建了一個這樣的 BaseService:
public abstract class BaseService<TEntity, TRepository> : BaseService
where TEntity : class, IEntity
where TRepository : IRepository<TEntity>
{
#region Fields
/// <summary>
/// Data manager
/// </summary>
protected TRepository Repository { get; } =
ServiceCollectionHelper.GetElementFromDependencyInjection<TRepository>();
/// <summary>
/// Mapper
/// </summary>
protected IMapper Mapper { get; } = ServiceCollectionHelper.GetElementFromDependencyInjection<IMapper>();
#endregion
}
public abstract class BaseService
{
}
ServiceCollectionHelper
:
public static class ServiceCollectionHelper
{
#region Fields
/// <summary>
/// Service collection
/// </summary>
private static IServiceProvider _serviceProvider = null;
/// <summary>
/// Service provider getter
/// </summary>
private static IServiceProvider ServiceProvider
{
get
{
if (_serviceProvider != null) return _serviceProvider;
//Get the service collection
_serviceProvider = new ServiceCollection().BuildServiceProvider();
return _serviceProvider;
}
}
#endregion
/// <summary>
/// Get an element from the dependency injection
/// </summary>
/// <typeparam name="TElement">Element type</typeparam>
/// <returns>Element</returns>
public static TElement GetElementFromDependencyInjection<TElement>()
{
return ServiceProvider.GetService<TElement>();
}
}
繼承自BaseService
的服務示例:
public class DepartmentService : BaseService<Department, IDepartmentRepository>
{
#region Fields
#endregion
#region Constructor
#endregion
#region Methods
/// <summary>
/// Get all departments
/// </summary>
/// <param name="withAdjacentDepartments">Include adjacent departments</param>
/// <param name="withRegion">Include region</param>
/// <returns>Departments</returns>
public async Task<IEnumerable<DepartmentDTO>> GetAsync(bool withAdjacentDepartments = false,
bool withRegion = false)
{
//Get departments
var departments = await this.Repository.GetAsync(withAdjacentDepartments, withRegion);
//Map to the DTO
return departments.Select(department => this.Mapper.Map<DepartmentDTO>(department)).ToList();
}
#endregion
}
問題是:找不到映射器和存儲庫,因此它們是 null。
我怎么能意識到這一點?
關於您在上面顯示的內容,我首先認識到的是您使用的是服務定位器模式而不是依賴注入,並且考慮到您使用的是 ASP NET Core DI 容器(或者在簡短的看看你的代碼庫),它使你的代碼比它需要的復雜得多。
在啟動期間,您正在注冊可能需要在整個代碼中調用的所有服務,但是當您實例化類並嘗試go 追捕它。
您遇到的具體問題是您正在嘗試設置 IServiceProvider 的一些全局 static 實例,但您從未將任何服務放入其中。 由於您沒有設置器,因此當您的定位器第一次嘗試使用 static 助手 class 獲取某些東西時,它會通知一個空集合並返回它,並且該實例與您在啟動期間注冊的實例完全分開。
也就是說,與“修復”全局 static 輔助實例相比,一些重組將是一條更好的前進道路。 考慮以下代碼:
public class Foo
{
public int Bar;
public int Qux;
}
public interface IRepository<T> where T : class, new()
{
T GetEntity();
}
public class FooRepository : IRepository<Foo>
{
public Foo GetEntity()
{
return new Foo();
}
}
public abstract class BaseService<TEntity>
where TEntity : class, new()
{
protected readonly IRepository<TEntity> _entityRepository;
protected readonly IMapper _mapper;
protected BaseService(IRepository<TEntity> entityRepository, IMapper mapper)
{
_entityRepository = entityRepository;
_mapper = mapper;
}
}
public interface IFooService
{
Foo ServicyStuff();
}
public class FooService : BaseService<Foo>, IFooService
{
public FooService(IRepository<Foo> entityRepository, IMapper mapper) : base(entityRepository, mapper)
{
}
public Foo ServicyStuff()
{
var foo = _entityRepository.GetEntity(); // Our abstract class handled this for us!
return foo;
}
}
以及啟動時的以下服務注冊:
services.AddAutoMapper(AppDomain.CurrentDomain.GetAssemblies());
services.AddTransient<IRepository<Foo>, FooRepository>();
services.AddTransient<IFooService, FooService>();
我們現在可以將一個 IFooService 實例傳遞給控制器或其他支持 DI 的服務,一切都已連接並准備好 go。 當 IFooService 解析 FooService 時,FooService 解析存儲庫並使用抽象基 class 來確保存儲庫在實例化期間被注入並可供繼承的類使用。 DI 容器負責您嘗試使用服務定位器抽象 class 和擴展解決的所有艱苦工作。
public class HomeController : Controller
{
private readonly ILogger<HomeController> _logger;
private readonly IFooService _fooService;
public HomeController(ILogger<HomeController> logger, IFooService fooService)
{
_logger = logger;
_fooService = fooService;
}
public IActionResult Index()
{
var myFoo = _fooService.ServicyStuff();
return View();
}
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.