将泛型类转换为其基本的非泛型类 - c#

7

我有以下的类:

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-children 接口的解决方案已经实现:

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);
            }
        }
    }
6个回答

7

您可以将WalkHierarchy方法移至基类并使其成为虚拟的。基类实现仅处理当前节点。对于CustomerWithChildern<T>类,重写将执行实际遍历。


这是最佳解决方案,因为它封装了步行实现,并且只需执行正确的操作,而不强制调用者了解实现细节。 - recursive
来自一个名叫"recursive"的人的高度赞扬。;-) - John Saunders
我的最后一个大型.NET项目有类似的要求,而John Saunders的方法很像我做的方式。这样做使得许多事情变得更容易 :) - OregonGhost

3

试试这个:

if(start.GetType().GetGenericTypeDefinition() == typeof(CustomerWithChildern<>))

2

"Is" 和 "As" 只能用于完全限定的泛型类型。

有关详细信息,包括解决方法,请参见 此 MSDN 讨论

我见过的最常见的解决方法是将一个接口添加到 CustomerWithChildren 中,并检查该接口。


2
我相信您希望为确定步行的查找添加一个接口。
因此,可以添加一个“IWalkable”接口,公开执行步行所需的信息,然后您可以创建一个方法来检查传递的对象是否实现了该接口。

1

我认为每个人在首次使用泛型类时都会遇到这个“问题”。

你的第一个问题可以从你的问题陈述中看出来:开放式泛型类型不是封闭式泛型类型的基类。这里根本没有面向对象的关系。真正的基类是CustomerBase。 “开放式”泛型类型就像是一个未完成的类;指定类型参数“关闭”它,使其完整。

虽然你可以这样做:

Type t = typeof(CustomerWithChildern<>)

条件

typeof(CustomerWithChildern<>).IsAssignableFrom(CustomerWithChildern<Foo>)

将始终为False。

-Oisin


0

就那个方法而言,不能。但是你可以通过接口实现相同的功能。事实上,你可以让你的泛型类实现IEnumerable。值得注意的是,为了确保类型安全,你的类还应该有“where T:CustomerBase”的限制。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接