将 StatePrinter 配置为仅遵循声明的类型?

Configure StatePrinter to only follow the declared types?

我正在使用 Stateprinter 来 print/compare 我的类型。它工作得很好,但是,它确实比较每个(子)对象的 实际 类型而不是子对象的声明类型。

一个例子:

class X {
  string Foo;
  int Bar;
}

interface IMyData {
  public X MyConfig { get; }
}

现在,调用时:

var cfg = ConfigurationHelper.GetStandardConfiguration();
cfg.Add(new PublicFieldsAndPropertiesHarvester());
var printer = new Stateprinter(cfg);

// ...

IMyData v = new MyDataWithMoreStuff();

printer.PrintObject(v);

这将打印 MyDataWithMoreStuff 的所有 public 字段和属性,而不仅仅是通过 IMyData.

可见的 public 状态

有没有办法用 Stateprinter 做到这一点,或者如果目前没有实现,是否有可能使用 C# 反射来遍历 "member tree"任意对象,而不是根据它们在运行时具有的具体类型来处理字段,而是根据变量声明的(基本/接口)类型?

从 v2.1.xx 开始,您现在可以根据其他类型指定类型的投影。 IE。执行以下操作

    [Test]
    public void TestIncludeByType()
    {
        var sut = new AtoD();
        Asserter assert;

        assert = TestHelper.CreateShortAsserter();
        assert.PrintEquals("new AtoD() { A = 1 B = 2 C = 3 D = 4 }", sut);

        assert = TestHelper.CreateShortAsserter();
        assert.Project.IncludeByType<AtoD, IA>();
        assert.PrintEquals("new AtoD() { A = 1 }", sut);

        assert = TestHelper.CreateShortAsserter();
        assert.Project.IncludeByType<AtoD, IA, IB>();
        assert.PrintEquals("new AtoD() { A = 1 B = 2 }", sut);

        assert = TestHelper.CreateShortAsserter();
        assert.Project.IncludeByType<AtoD, IA, IB, IC>();
        assert.PrintEquals("new AtoD() { A = 1 B = 2 C = 3 }", sut);

        assert = TestHelper.CreateShortAsserter();
        assert.Project.IncludeByType<AtoD, IA, IB, IC, ID>();
        assert.PrintEquals("new AtoD() { A = 1 B = 2 C = 3 D = 4 }", sut);
    }

    [Test]
    public void TestExcludeByType()
    {
        var sut = new AtoD();
        Asserter assert;

        assert = TestHelper.CreateShortAsserter();
        assert.PrintEquals("new AtoD() { A = 1 B = 2 C = 3 D = 4 }", sut);

        assert = TestHelper.CreateShortAsserter();
        assert.Project.ExcludeByType<AtoD, IA>();
        assert.PrintEquals("new AtoD() { B = 2 C = 3 D = 4 }", sut);

        assert = TestHelper.CreateShortAsserter();
        assert.Project.ExcludeByType<AtoD, IA, IB>();
        assert.PrintEquals("new AtoD() { C = 3 D = 4 }", sut);

        assert = TestHelper.CreateShortAsserter();
        assert.Project.ExcludeByType<AtoD, IA, IB, IC>();
        assert.PrintEquals("new AtoD() { D = 4 }", sut);

        assert = TestHelper.CreateShortAsserter();
        assert.Project.ExcludeByType<AtoD, IA, IB, IC, ID>();
        assert.PrintEquals("new AtoD() { }", sut);
    }

但这是基于类型的过滤,而不是基于引用类型的一般状态收集。那,我不认为现在的代码是这样的:

 class IntroSpector  
 {
    void Introspect(object source, Field field)
    {
        if (IntrospectNullValue(source, field))
            return;

        var sourceType = source.GetType();

        ...

因此 StatePrinter 要求提供基础类型 (GetType())。您可能需要重载该方法,或者可能更好,编写一个 ReferenceAwareIntrospector 代码,它接受第三个参数,即引用参数,并使用它。

这样做应该相当容易,并且使内省器可配置同样是 Configuration class.

的简单扩展