我想通过实例的属性创建XML文档。为此,我写了两个扩展名。
<Extension()>
Public Function ToXml(Of T)(ByVal source As T) As XmlDocument
Dim oXmlDocument As New XmlDocument
oXmlDocument.AppendChild(oXmlDocument.CreateXmlDeclaration("1.0", "utf-8", Nothing))
oXmlDocument.AppendChild(oXmlDocument.CreateElement(XmlConvert.EncodeName(source.GetType.ToString)))
For Each Item As System.Reflection.FieldInfo In source.GetType.GetFields
Dim oElement As XmlElement = oXmlDocument.CreateElement(Item.Name)
oElement.Attributes.Append(oXmlDocument.CreateAttribute("Value")).Value = Item.GetValue(Nothing).ToString
oXmlDocument.DocumentElement.AppendChild(oElement)
Next
Return oXmlDocument
End Function
<Extension()>
Public Function ToXml(Of T)(ByVal source As IEnumerable(Of T)) As XmlDocument
Dim oXmlDocument As New XmlDocument
oXmlDocument.AppendChild(oXmlDocument.CreateXmlDeclaration("1.0", "utf-8", Nothing))
oXmlDocument.AppendChild(oXmlDocument.CreateElement(XmlConvert.EncodeName(source.GetType.ToString)))
For Each Item As T In source
oXmlDocument.DocumentElement.AppendChild(oXmlDocument.ImportNode(Item.ToXml.DocumentElement, True))
Next
Return oXmlDocument
End Function
第二种方法应该是IEnumerable(Of T)
类型,第一种方法适用于所有其他类型。如果我尝试使用Button
,String
,Int32
或类似的实例,则可以正常使用。对于List(Of T)
的实例,也将调用第一种方法。似乎忽略IEnumerable(Of T)
的扩展名,因为T的扩展范围更宽。
是否有可能强制List(Of T)
使用IEnumerable(Of T)
的扩展程序?
答案 0 :(得分:0)
overload "signature"不包含通用约束,因此使用Of T
子句调整As
似乎没有帮助。
对于简单(非泛型)接口,会出现相同的“问题”,因为选择与类最接近的匹配来使用重载。
所以请注意,对于某些课程,List(Of Integer)
说,这两个签名是ToXml(List(Of Integer))
和ToXml(IEnumerable(Of Integer))
,因此它会明确选择前者,完全匹配。
因为“不是最具体的”。错误,我甚至没有一个解决方案,可以让你给未来的编码员提示他们称错了例行程序。我可以建议的最好的方法是不对可能是列表的对象使用重载: - (
即。有ToXmlFromObject(Of T)(ByVal source As T)
和ToXmlFromList(Of T)(ByVal source As IEnumerable(Of T))
并且,在运行时(:-(),您可以使用ToXmlFromObject
中的反射来检查Enumerables的使用情况。像这样的东西(直接输入SO文本框):
Debug.Assert(GetType(T) Is GetType(String) _
OrElse Not (From i In GetType(T).GetInterfaces() _
Where i Is GetType(IEnumerable)).Any)
我还应该提到一些错误消息暗示的另一个选项:您可以继续重载ToXml(As T)
和ToXml(As IEnumerable(Of T))
,但不要依赖隐含的重载。即明确列出(Of ElementType)
以确保调用ToXml(Of ElementType)(As IEnumerable(Of ElementType))
版本。 (当SomeType
实施IEnumerable(Of SomeType)
时,这仍然会失败。)
正如我在评论中提到的,这会失败,因为您要在T
演员表中指定IEnumerable(Of )
的其他类型。
此外,我现在注意到这会失败,因为使用ToXml
调用IEnumerable(Of Anything)
会出错,因为上面描述的两个签名都是相同的,因此错误“重载解析失败,因为无法访问” ToXml'对这些参数最具体:......不是最具体的......不是最具体的。“。
我认为你唯一的选择就是在另一个方向上手动“强制”超载;即在确切的情况下,检查接口是否匹配,并调用该过载:
<Extension()>
Public Function ToXml(Of T)(ByVal source As T) As XmlDocument
Dim enumSource = TryCast(source, IEnumerable(Of T))
If enumSource IsNot Nothing Then Return ToXml(enumSource)
...