12

我一直在寻找允许我将任意 C# 对象传递给 XSL 转换的组件。

这样做的天真方法是使用 XmlSerializer 序列化对象图;但是,如果您有一个大型对象图,就性能而言,这可能会导致问题。循环引用、延迟加载、代理等问题可能会进一步搅浑这里的水。

更好的方法是拥有某种实现 IXPathNavigable 和 XPathNavigator 的适配器类。我遇到的一个这样的例子是Byte-Force 的 ObjectXPathNavigator —— 然而,它的大部分关键文档都是俄语的,我最初的测试似乎表明它有一些怪癖和特质。

有没有人知道 (a) 任何关于此特定英语的资源(概述、教程、博客文章等)或 (b) 提供相同或相似功能的任何其他替代方案?

4

4 回答 4

7

有一篇(非常)旧的 MSDN 文章,标题为XPath Querying Over Objects with ObjectXPathNavigator,它实现了一个类似的类(也称为 ObjectXPathNavigator,很有趣)。我很久以前就用它从 Visual SourceSafe 查询一些数据并从更改日志构建一个 RSS 提要,它工作得很好。但是,我没有用它做 XSLT,所以我不确定它是否有效。另外,请注意它是为 Framework 1.0 编写的,因此您可能需要为更新的框架更新它。此外,现在可能有更好的方法来做到这一点,但它会给你一个起点(这篇文章很好地解释了它的工作原理)。

于 2009-11-13T21:09:25.200 回答
2

Sounds as though the problem you're trying to solve is quite interesting.

At first glance, I'd suggest writing your own implementation of an XPathNavigator descendant - there are only 20-odd methods to write, and none of them have a particularly difficult signature.

A naive implementation using non-cached reflection would be slow(ish) but would work well as a proof of concept and you could make changes to improve performance if/when that became an issue.

However ...

... I think you may run into some difficulties that stem from your approach, not from any implementation detail.

An XML file is (by nature) a simple hierarchy of elements and attributes - there are no loops (aka cycles) in the node graph.

An XPath expression can include the operator "//" which broadly means to search to unlimited depth. (For an exact definition, see section 2.5 of XPath 1.0.)

If you applied such an expression to an object graph with cross references (aka object cycles), then you run the risk of the XPath evaluator going into an infinite loop as it tried to recursively enumerate an effectively infinite graph.

You may be able to work around this issue by somehow keeping track of parent nodes in your XPathNavigator and throwing an exception if a loop is detected, but I'm not sure how viable this will be.

于 2009-01-10T23:02:30.110 回答
0

由于对象图可能是循环的,因此您不可能从中创建基于树的结构。最好的办法是用最简单的组件来表示对象图:节点和向量。

更具体地说,使每个节点(对象)成为具有唯一 ID 的元素(可能由 C# 的 GetHashCode() 方法提供?)。对其他对象(向量)的引用将通过引用对象的 ID 来处理。

示例类(请注意,我不懂 C#,所以我的语法可能有点偏离):

public class SomeType {
   public int myInt  { get; set; }
}

public class AnotherType {
   public string myString { get; set; }
   public SomeType mySomeType { get; set; }
}

public class LastType {
   public SomeType mySomeType { get; set; }
   public AnotherType myAnotherType { get; set; }
}

public class UserTypes{
    static void Main()
    {
        LastType lt = new LastType();
        SomeType st = new SomeType();
        AnotherType atype = new AnotherType();

        st.myInt = 7;
        atype.myString = "BOB";
        atype.mySomeType = st;
        lt.mySomeType = st;
        lt.myAnotherType = atype;

        string xmlOutput = YourAwesomeFunction(lt);
    }
}

然后我们期望 xmlOutput 的值是这样的(注意选择的 ID 值是完全合成的):

<ObjectMap>
 <LastType id="0">
   <mySomeType idref="1" />
   <myAnotherType idref="2" />
 </LastType>

 <SomeType id="1">
  <myInt>7</myInt>
 </SomeType>

 <AnotherType id="2">
  <myString>BOB</myString>
  <mySomeType idref="1" />
 </AnotherType>
</ObjectMap>
于 2009-01-21T18:54:48.390 回答
0

你可以尝试这样的事情:

http://code.google.com/p/antix-software/wiki/AntixReflectionQuery

于 2013-02-15T09:56:27.693 回答