我有一些C#代码,它们使用.NET框架中的Xml.Schema类来遍历XML模式。框架中将各种简单的类型限制抽象为从Xml.Schema.XmlSchemaFacet派生的一堆类。除非有我遗漏的东西,否则了解给定构面是哪种派生构面类型的唯一方法是,将其投机地转换为其中一个构面,以防失败时捕获结果InvalidCastOperation。这样做给我留下了一个非常丑陋的功能,如下所示:

private void NavigateFacet(XmlSchemaFacet facet)
{
    try
    {
        handler.Length((XmlSchemaLengthFacet)facet);
    }
    catch(InvalidCastException)
    {
        try
        {
            handler.MinLength((XmlSchemaMinLengthFacet)facet);
        }
        catch(InvalidCastException)
        {
            try
            {
                handler.MaxLength((XmlSchemaMaxLengthFacet)facet);
            }
            catch(InvalidCastException)
            {
                ...
            }
        }
    }
}


我认为必须有更优雅的方法来做到这一点;使用我从.NET框架中缺少的某些属性,或者使用一些巧妙的OO技巧。谁能启发我?

最佳答案

因为我更喜欢调试数据而不是调试代码,所以我会这样做,尤其是在代码必须处理所有XmlSchemaFacet子类的情况下:

Dictionary<Type, Action<XmlSchemaFacet>> HandlerMap =
   new Dictionary<Type, Action<XmlSchemaFacet>>
{
   {typeof(XmlSchemaLengthFacet), handler.Length},
   {typeof(XmlSchemaMinLengthFacet), handler.MinLength},
   {typeof(XmlSchemaMaxLengthFacet), handler.MaxLength}
};

HandlerMap[facet.GetType()](facet);


如果KeyNotFoundException不是已知类型,则会抛出facet。请注意,所有处理程序方法都必须从XmlSchemaFacet强制转换其参数,因此您可能没有节省代码的总行数,但肯定是节省了遍历代码的路径数。

还有一点(假设映射是预先构建的),将类型映射到带有字典的方法比遍历类型的线性列表要快,这实际上就是使用一堆if块可以使您得到的。

09-28 09:25