为什么要在泛型类型中限制接口
本文关键字:接口 泛型类型 为什么 | 更新日期: 2023-09-27 18:31:53
在
C# 中对泛型的接口类型进行约束有什么意义? 例如
public interface IHandler<in T>
where T : IProcessor
{
void Handle(T command);
}
简单地将 IProcessor 作为泛型继承而没有任何限制不是更好吗? 这样做有什么好处?
例如
public class FooProcessor : IProcessor<T>
{
void Handle(T command)
{
}
}
如果接口为空,则它是一个标记接口。
它可用于在类外部应用有关类的限制。为了与下面的示例保持一致,您可以将装饰器限制为只能装饰IProcessor
处理程序。
一个非常合理的原因是在应用装饰器时:
假设命令参数接口有几个属性:
public interface IProcessor
{
int Id { get; }
DateTime Date { get; }
}
我们可以在IProcessor
命令的所有处理程序上定义一个装饰器,这些命令知道所有命令参数都具有Id
和Date
:
public sealed class HandlerLogger<in T> where T : IProcessor
{
private readonly ILogger logger;
private readonly IHandlerLogger<T> decorated;
public HandlerLogger(
ILogger logger,
IHandlerLogger<T> decorated)
{
this.logger = logger;
this.decorated = decorated;
}
public void Handle(T command)
{
this.logger.Log(command.Id, command.Date, typeof(T).Name);
this.decorated.Handle(command);
}
}
有不同的体系结构模式可用于实际强制实施类型。
例如,如果您正在设计一个 API,并且希望允许某人扩展它,但您希望确保为扩展框架而创建的类是特定类型,并且具有默认的无参数构造函数。 使用泛型类型化接口是执行此操作的常用方法。
我创建了一个快速示例adhoc,以相对简单地概述为什么类型化接口在某些模型/体系结构设计中很有用。
public class UnitOfWorkManager<T>
{
private readonly IDataRepository _dataRepository;
private List<T> _unitOfWorkItems;
public UnitOfWorkManager(IDataRepository dataRepository)
{
_dataRepository = dataRepository;
}
public void AddUnitOfWork(IUnitOfWork<T> unitOfWork)
{
this._unitOfWorkItems.Add(unitOfWork);
}
public void Execute()
{
WorkerItem previous = null;
foreach (var item in _unitOfWorkItems)
{
var repoItem = _dataRepository.Get(item.Id);
var input = new WorkerItem(item.Id, repoItem.Name, previous);
previous = input;
}
}
}
public interface IUnitOfWork<T>
where T: WorkerItem, new()
{
string Id { get; }
void Execute(T input);
}
public class WorkerItem
{
public WorkerItem(string id, string name, WorkerItem previous)
{
this.Name = name;
this.Id = id;
this.Previous = previous;
}
public string Id { get; private set; }
public string Name { get; private set; }
public WorkerItem Previous { get; private set; }
}
希望这有帮助。