我有以下课程:
public abstract class CustomerBase
{
public long CustomerNumber { get; set; }
public string Name { get; set; }
}
public abstract class CustomerWithChildern<T> : CustomerBase
where T: CustomerBase
{
public IList<T> Childern { get; private set; }
public CustomerWithChildern()
{
Childern = new List<T>();
}
}
public class SalesOffice : CustomerWithChildern<NationalNegotiation>
{
}
SalesOffice只是代表不同级别的客户层次结构的少数几个类别之一。现在我需要从某个角度(CustomerBase)遍历这个层次结构。我不知道如何在不使用反射的情况下实现。我想实现类似的东西:
public void WalkHierarchy(CustomerBase start)
{
Print(start.CustomerNumber);
if (start is CustomerWithChildern<>)
{
foreach(ch in start.Childern)
{
WalkHierarchy(ch);
}
}
}
我有没有机会得到这样的工作?
该解决方案基于我实现的has-childern接口:
public interface ICustomerWithChildern
{
IEnumerable ChildernEnum { get; }
}
public abstract class CustomerWithChildern<T> : CustomerBase, ICustomerWithChildern
where T: CustomerBase
{
public IEnumerable ChildernEnum { get { return Childern; } }
public IList<T> Childern { get; private set; }
public CustomerWithChildern()
{
Childern = new List<T>();
}
}
public void WalkHierarchy(CustomerBase start)
{
var x = start.CustomerNumber;
var c = start as ICustomerWithChildern;
if (c != null)
{
foreach(var ch in c.ChildernEnum)
{
WalkHierarchy((CustomerBase)ch);
}
}
}
答案 0 :(得分:7)
您可以将WalkHierarchy方法移动到基类并使其成为虚拟。基类实现只处理当前节点。对于CustomerWithChildern<T>
类,覆盖将执行实际操作。
答案 1 :(得分:3)
试试这个:
if(start.GetType().GetGenericTypeDefinition() == typeof(CustomerWithChildern<>))
答案 2 :(得分:2)
“Is”和“As”仅适用于完全限定的泛型类型。
有关详细信息,包括解决方法,请参阅this MSDN discussion。
我见过的最常见的解决方法是在CustomerWithChildren可以实现的混合中添加一个接口,并检查该接口。
答案 3 :(得分:2)
我相信你想查找确定对步行界面做的事情。
因此,可以添加一个“IWalkable”接口来公开执行walk所需的信息,然后您可以创建方法检查以查看传递的对象是否实现了接口。
答案 4 :(得分:1)
我认为在第一次使用泛型类时,每个人都会遇到这个“问题”。
你的第一个问题在你的问题中被暗示:一个开放的泛型类型不是封闭的类型的基类。根本没有OO关系。真正的基类是CustomerBase。 “开放”泛型类似于半完成类;指定类型参数“关闭”它,使其完整。
虽然你能做到:
Type t = typeof(CustomerWithChildern<>)
条件
typeof(CustomerWithChildern<>).IsAssignableFrom(CustomerWithChildern<Foo>)
永远是假的。
-Oisin
答案 5 :(得分:0)
明确地使用该方法,没有。但是,您可以使用界面实现相同的功能。实际上,您可以让您的泛型类实现IEnumerable。同样值得注意的是,您的班级也应该有“T:CustomerBase”,以确保类型安全。