如何使这个通用界面更加Typed?

时间:2011-07-11 20:15:28

标签: c# generics

考虑使用角色对象的类,维护集合来执行此操作。可能存在对是否可以添加给定角色的限制,以及如果可以添加它应该发生的动作。

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

但是我想让IRoleSpecification.PreInsert处理程序使用泛型类型(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; }
}

1 个答案:

答案 0 :(得分:1)

有没有理由你不能宣布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 - 去) - 因为那时接口是协变的。泛型参数不能兼容和反变。