考虑使用角色对象的类,维护集合来执行此操作。可能存在对是否可以添加给定角色的限制,以及如果可以添加它应该发生的动作。
下面的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; }
}
答案 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
- 去) - 因为那时接口是协变的。泛型参数不能兼容和反变。