Как я могу сделать этот общий интерфейс более типизированным?

79
7

Рассмотрим класс, который использует объекты ролей, поддерживая коллекцию для этого. Могут быть ограничения на возможность добавления заданной роли, а также действия, которые должны иметь место, если они могут быть добавлены.


Ниже приведено описание IRoleSpecication, чтобы отделить ответственность за добавление решения и действия от класса, поддерживающего сбор, поэтому у меня есть рабочий код (то есть полезный), который выглядит как пример кода ниже.


НО Я бы хотел, чтобы обработчик IRoleSpecification.PreInsert использовал общий тип (TRole) вместо объекта, который он использует в настоящее время. Я попытался добавить параметр для TRole, но мой существующий код хотел, чтобы он оставался ковариантным, в то время как этот метод требовал его инвариантности.


Как я могу это сделать?


Cheers,

Беррил


public interface IRoleSpecification<in T>
{

bool CanAddRoleFor(T instance);

/// <summary>
/// Called when the newRole is about to be added to instance 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; }
}

спросил(а) 2021-01-19T13:54:13+03:00 9 месяцев, 1 неделя назад
1
Решение
65

Есть ли какая-либо причина, по которой вы не можете объявить, что 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 содержит член (который вы здесь опущены), который предоставляет TROL (out -going), потому что тогда интерфейс является ковариантным. Общий параметр не может быть и ко-контравариантным.

ответил(а) 2021-01-19T13:54:13+03:00 9 месяцев, 1 неделя назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема