我有一个泛型类型(RoleEntity),它可能实现也可能不实现也是泛型的接口(IActor)。设计背景如下,但简短的故事是 RoleEntity 是一个可能由 Actor 承担的角色,并且 RoleEntity可以选择是具有自己角色的 IActor。
因此,如果我想访问演员角色的角色,我可以想到两个选项
- 将角色安全地投射到 Actor{T}。如果我不将一种泛型转换为另一种泛型,我会这样做;似乎做到这一点的唯一方法是进行一些重要的反思。
- 使用动态。
下面的代码是两者的混搭。我正在使用反射,但还不足以真正找出确切的 IActor{T}。然后因为我有一个不确定的类型,所以我使用 IEnumerable{dynamic}。感觉不是很好的代码,但我不知道如何做得更好。
有人可以提供一些更简洁的代码吗?
static void GetRoleHeirarchyString<T>(IActor<T> actor)
where T : Entity, IActor<T>
{
foreach (var role in actor.AllRoles) {
// do something with the Role;
// trivial reflection
var type = role.GetType();
var pi = type.GetProperty("AllRoles");
if (pi == null)
continue;
var roles = pi.GetValue(role, null) as IEnumerable<dynamic>; // dynamic
foreach (var r in roles) {
// do something with the Role;
}
}
}
背景
下面是两个接口,它们是实现角色的解决方案的一部分。在此设计中,可以表示为一个或多个角色的类称为 Actor。表达角色的类(称为“角色”!)使用 Actor 的实例来转发来自 Actor 的感兴趣的属性。例如,如果一个 Person 类是应用程序中多个角色(即学生、母亲和员工)的 Actor,那么每个角色可能会使用 Person 的一个实例来拥有一个基于 Person 的公共 Name 属性。
角色可能也可能不是演员;员工可能是项目经理,甚至可能是其雇主所销售产品的买家。但是一个学生可能只是一个人的角色而不是一个演员。
public class RoleEntity<T> : Entity where T : Entity, IActor<T>
{
public T Actor { get; protected set; }
...
}
public interface IActor<T> where T : Entity, IActor<T>
{
bool AddRole(IRoleFor<T> role);
bool RemoveRole(IRoleFor<T> role);
bool HasRole(IRoleFor<T> role);
IEnumerable<IRoleFor<T>> AllRoles { get; }
}