我有一些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
块可以使您得到的。