Xml T的重载扩展方法
我想通过实例的属性创建一个XML文档。为此,我编写了两个扩展Xml T的重载扩展方法,xml,vb.net,reflection,types,extension-methods,Xml,Vb.net,Reflection,Types,Extension Methods,我想通过实例的属性创建一个XML文档。为此,我编写了两个扩展 公共函数ToXml(Of T)(ByVal源代码为T)作为XmlDocument Dim oXmlDocument作为新的XmlDocument AppendChild(oXmlDocument.CreateXmlDeclaration(“1.0”,“utf-8”,Nothing)) AppendChild(oXmlDocument.CreateElement(XmlConvert.EncodeName(source.GetType
公共函数ToXml(Of T)(ByVal源代码为T)作为XmlDocument
Dim oXmlDocument作为新的XmlDocument
AppendChild(oXmlDocument.CreateXmlDeclaration(“1.0”,“utf-8”,Nothing))
AppendChild(oXmlDocument.CreateElement(XmlConvert.EncodeName(source.GetType.ToString)))
对于source.GetType.GetFields中的System.Reflection.FieldInfo等每个项
Dim oElement作为XmlElement=oXmlDocument.CreateElement(Item.Name)
oElement.Attributes.Append(oXmlDocument.CreateAttribute(“值”)).Value=Item.GetValue(Nothing.ToString
oXmlDocument.DocumentElement.AppendChild(oElement)
下一个
返回OXML文档
端函数
公共函数ToXml(Of T)(ByVal源代码为IEnumerable(Of T))作为XmlDocument
Dim oXmlDocument作为新的XmlDocument
AppendChild(oXmlDocument.CreateXmlDeclaration(“1.0”,“utf-8”,Nothing))
AppendChild(oXmlDocument.CreateElement(XmlConvert.EncodeName(source.GetType.ToString)))
对于源中的每一项作为T
oXmlDocument.DocumentElement.AppendChild(oXmlDocument.ImportNode(Item.ToXml.DocumentElement,True))
下一个
返回OXML文档
端函数
第二种方法适用于IEnumerable(Of T)
的类型,第一种方法适用于所有其他类型。如果我在按钮
、字符串
、Int32
或类似的实例中尝试它,效果会很好。对于实例,即List(of T)
,也将调用第一个方法。似乎忽略了IEnumerable(Of T)
的扩展,因为T的扩展范围更广
是否有可能强制列表(Of T)
使用IEnumerable(Of T)
的扩展名?不包括泛型约束,因此用As
子句调整Of T
似乎没有帮助
对于简单(非泛型)接口,也会出现相同的“问题”,即选择与类最接近的匹配项,以便重载使用
请注意,对于某些类,List(Of Integer)
例如,这两个签名是ToXml(List(Of Integer))
和ToXml(IEnumerable(Of Integer))
,因此它将明确选择前者,这是一个精确匹配
由于“不是最具体的”错误,我甚至没有一个解决方案可以让你给未来的程序员一个提示,他们调用了错误的例程。我所能建议的最好方法是不要对可以是列表的对象使用重载:-(
也就是说,拥有ToXmlFromObject(Of T)(ByVal源为T)
和ToXmlFromList(Of T)(ByVal源为IEnumerable(Of T))
并且,在运行时(:-(),您可以使用ToXmlFromObject
中的反射来检查枚举的使用情况
我还应该提到一些错误消息暗示的另一个选项:您可以继续重载
ToXml(As T)
和ToXml(As IEnumerable(Of T))
,但不要依赖于隐含的重载。例如,显式列出(Of ElementType)
以确保ToXml(Of ElementType)(As IEnumerable(Of ElementType))
version被调用。(当您确实有SomeType
实现IEnumerable(SomeType)
时,此操作仍然会失败)
错误答案 正如我在评论中提到的,这失败了,因为您希望在
IEnumerable(Of)
cast中指定一个不同的类型T
另外,我现在注意到这将失败,因为使用IEnumerable(任何内容)
调用ToXml
会出错,因为上面描述的两个签名都是相同的,所以它会出现“重载解析失败,因为没有可访问的'ToXml'对这些参数最具体:……不是最具体的……不是最具体的”的错误
我认为您唯一的选择是在另一个方向手动“强制”重载;即,在确切的情况下,检查接口是否匹配,并调用该重载:
公共函数ToXml(Of T)(ByVal源代码为T)作为XmlDocument
Dim enumSource=TryCast(源,IEnumerable(共T个))
如果enumSource不是Nothing,则返回ToXml(enumSource)
...
我已经编辑了你的标题。请参见“”,其中的共识是“不,他们不应该”。
Debug.Assert(GetType(T) Is GetType(String) _
OrElse Not (From i In GetType(T).GetInterfaces() _
Where i Is GetType(IEnumerable)).Any)