如何使这个泛型接口更类型化?

本文关键字:类型化 泛型接口 何使这 | 更新日期: 2023-09-27 18:01:51

考虑一个使用角色对象的类,维护一个集合来这样做。对于是否可以添加给定的角色,以及如果可以添加角色应该执行的操作,可能存在限制。

下面的IRoleSpecication旨在将add决策和操作的责任与维护集合的类分开,因此我有工作代码(即有用的),看起来像下面的代码示例。

但是我想做irolspecification。预插入处理程序使用泛型类型(TRole)而不是它当前使用的对象。我尝试为TRole添加一个参数,但我现有的代码希望它保持协变,而该方法需要它是不变的。

我该怎么做呢?

欢呼,
Berryl

public interface IRoleSpecification<in T>
{
     bool CanAddRoleFor(T instance);
    /// <summary>
    /// Called when the newRole is about to be added to instance's collection of roles.
    /// </summary>
    /// <param name="instance">The instance.</param>
    /// <param name="newRole">The new role.</param>
    void OnPreInsert(T instance, object newRole);
    ...
}
public interface IEmployeeRoleSpecification<out TRole> : IRoleSpecification<EmployeeEx> where TRole : EmployeeRole
{
     bool IsJobRole { get; set; }
}
public abstract class EmployeeRoleSpecification<TRole> : ValueObject, IEmployeeRoleSpecification<TRole> 
    where TRole : EmployeeRole
{
    public virtual bool CanAddRoleFor(EmployeeEx employee) { return false; }
    public virtual void OnPreInsert(EmployeeEx instance, object newRole) {
        // jobRole helps enforce role constraints
        // employee may have only one job role for 'job' role specs
        if (IsJobRole) {
            instance.JobRole = (TRole) newRole;
        }
    }
    ....
}
<标题> 更多代码
public class EmployeeRole : EmployeeEx
{
    private static readonly ISet<IEmployeeRoleSpecification<EmployeeRole>> _creationSpecs;
    static EmployeeRole() {
        _creationSpecs = new HashSet<IEmployeeRoleSpecification<EmployeeRole>>
                         {
                             new SalesmanRoleSpecification(),
                             new EngineerRoleSpecification(),
                             new ManagerRoleSpecification(),
                         };
    }
}

public class SalesmanRoleSpecification : EmployeeRoleSpecification<Salesman>
{
    public override bool CanAddRoleFor(EmployeeEx employee) { return _checkCanAddJobRole(employee); }
    public SalesmanRoleSpecification() { IsJobRole = true; }
}

如何使这个泛型接口更类型化?

是否存在不能声明IEmployeeRoleSpecification为逆变的原因?

给定你发布的代码,这将编译:

public interface IEmployeeRoleSpecification<in TRole> : IRoleSpecification<EmployeeEx, EmployeeRole> where TRole : EmployeeRole
{
     bool IsJobRole { get; set; }
}
public abstract class EmployeeRoleSpecification<TRole> : IEmployeeRoleSpecification<TRole> 
    where TRole : EmployeeRole
{
    public virtual bool CanAddRoleFor(EmployeeEx employee) { return false; }
    public virtual void OnPreInsert(EmployeeEx instance, EmployeeRole newRole) {
        // jobRole helps enforce role constraints
        // employee may have only one job role for 'job' role specs
        if (IsJobRole) {
            instance.JobRole = newRole;
        }
    }
    public bool IsJobRole { get;set; }
}
public class EmployeeEx 
{
    public EmployeeRole JobRole { get;set;}
}
public class EmployeeRole { }

您可能无法做到这一点的原因是,如果IEmployeeRoleSpecification包含一个成员(您在这里省略了),则会暴露TRole (out -going) -因为这时接口是协变的。泛型形参不能同时为共变和逆变。