2

我想通过实例的属性创建一个 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

第二种方法应该适用于类型 by IEnumerable(Of T),第一种适用于所有其他类型。如果我尝试将它用于,或类似的实例Button,它可以正常工作。使用 ie 的实例也会调用第一个方法。似乎忽略了 for 的扩展,因为 T 的扩展范围更广。StringInt32List(Of T)IEnumerable(Of T)

是否有可能强制 aList(Of T)使用扩展名IEnumerable(Of T)

4

1 回答 1

0

重载“签名”不包括通用约束,因此调整Of TwithAs子句似乎没有帮助。

对于简单(非泛型)接口,会出现相同的“问题”,因为选择了与类最接近的匹配项以供重载使用。

因此请注意,对于某些类,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)and ToXml(As IEnumerable(Of T)),但不要依赖隐含的重载。即明确列出(Of ElementType)以确保ToXml(Of ElementType)(As IEnumerable(Of ElementType))调用版本。(当您确实SomeType实施时,这仍然会失败IEnumerable(Of SomeType)。)


错误的答案

正如我在评论中提到的,这失败了,因为您想TIEnumerable(Of )演员表中指定不同的类型。

另外我现在注意到这会失败,因为调用ToXmlwithIEnumerable(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)
  ...
于 2013-07-01T15:26:14.417 回答