我正在使用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
类的简单扩展。