将状态打印机配置为仅遵循声明的类型



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

举个例子:

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的所有公共字段和属性,而不仅仅是通过 IMyData 可见的公共状态。

有没有办法使用 Stateprinter 做到这一点,或者如果当前没有实现,是否可以使用 C# 反射来遍历任意对象的"成员树",而不是按运行时的具体类型处理字段,而是按声明变量的(基/接口)类型?

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

    [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();
        ...

所以状态打印机要求底层类型(GetType())。您可能需要重载该方法,或者更好的是,编写一个ReferenceAwareIntrospector,该采用第三个参数,即引用参数,并使用该参数。

这样做应该相当容易,并且使内省器可配置同样是Configuration类的简单扩展。

最新更新