简体   繁体   English

处理通用类型转换

[英]Dealing with a Generic Type cast

I have a generic type (RoleEntity) that may or may not implement an interface that is also generic (IActor). 我有一个通用类型(RoleEntity),它可能会也可能不会实现同样是通用(IActor)的接口。 Background on the design is below, but the short story is that a RoleEntity is a role that maybe assumed by an Actor and that RoleEntity may optionally be an IActor with it's own Roles. 设计的背景如下,但简短的故事是:RoleEntity是一个角色,可能由Actor承担,并且RoleEntity 可以选择是具有其自身角色的IActor。

So if I want to access the Roles of a an Actor's role, I can think of two options 因此,如果我想访问演员角色的角色,我可以想到两种选择

  1. Cast the role safely to an Actor{T}. 安全地将角色转换为演员{T}。 This is what I would do if I wasn't casting one generic to another; 如果我不将一个泛型转换为另一个泛型,那将是我要做的。 it seems the only way to do this is with some non-trivial reflection. 似乎唯一的方法就是进行一些非平凡的反思。
  2. Use dynamic. 使用动态。

The code below is a bastardized mix of both. 下面的代码是两者的混用。 I am using reflection but not far enough to actually figure out the exact IActor{T}. 我正在使用反射,但距离实际上还不足以真正找出确切的IActor {T}。 Then because I have an indeterminate type I use IEnumerable{dynamic}. 然后,因为我有一个不确定的类型,所以我使用IEnumerable {dynamic}。 It doesn't feel like good code but I don't know how to do better. 它看起来不像是好的代码,但我不知道如何做得更好。

Can someone present some cleaner code? 有人可以提供更简洁的代码吗?

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;
        }
    }
}

Backround 背景

Below are two interfaces that are part of a solution implementing Roles . 以下是实现Roles的解决方案的一部分的两个接口。 In this design, a class that might be expressed as one or more Roles is called an Actor. 在此设计中,可以表示为一个或多个角色的类称为Actor。 The class that is expressing a Role (called a 'Role'!) uses an instance of the Actor to forward properties of interest from the Actor. 表示角色的类(称为“角色”!)使用Actor的实例从Actor转发感兴趣的属性。 So for example, if a Person class is an Actor for several roles in an application )ie, Student, Mother, and Employee) then each Role might use an instance of the Person to have a common Name property that is based on the Person. 因此,例如,如果某个Person类是应用程序中多个角色(例如,学生,母亲和雇员)的Actor,则每个角色都可以使用Person的实例来具有基于Person的通用Name属性。

Roles may or may not also be Actors; 角色可能也可能不是演员; an Employee may be a ProjectManager or even a Buyer of something her employers sells. 雇员可能是项目经理,甚至是雇主出售的东西的买方。 But a Student may just be a role for a Person and not an Actor. 但是学生可能只是一个人而不是演员的角色。

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; }
}

Sometimes it is possible to define non-generic interface IRoleEntity and have your RoleEntity<T> implement IRoleEntity . 有时可以定义非通用接口IRoleEntity并让RoleEntity<T>实现IRoleEntity

If you declare a method IRole.DoSomethingWithTheRole, then you can implement it in RoleEntity<T> . 如果声明方法IRole.DoSomethingWithTheRole,则可以在RoleEntity<T>实现它。 And you can call it without knowing exact RoleEntity<T> type thanks to polymorphism. 由于多态性,您可以在不知道确切的RoleEntity<T>类型的情况下调用它。

Same trick you may want to do with IActor<T> inheriting IActor . 您可能想对IActor<T>继承IActor

It doesn't always make sense, but I don't have enough understanding of your problem. 这并不总是很有意义,但是我对您的问题没有足够的了解。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM