反射嵌套实例而不创建新实例
我一直在努力处理一些我认为很简单的反射代码。本质上,我有一个定义方法的接口。然后,我有一个抽象类,它提供该方法的基本实现。
具体类可以包含其他类的嵌套实例,这些类也可以从同一基类派生。可以通过以下示例来说明:
using System.Linq;
public interface ISampleObject
{
bool IsValid();
}
public abstract class SampleObjectBase : ISampleObject
{
public bool IsValid()
{
var returnValue = true;
// Self-validation sets the return value.
var childProperties = this.GetType().GetProperties().Where(pi => typeof(ISampleObject).IsAssignableFrom(pi.PropertyType));
foreach (var childProperty in childProperties)
{
// var childInstance = ????; // Need the actual *existing* instance property, cast to ISampleObject.
// if (childInstance.IsValid() != true)
// {
// returnValue = false;
// }
}
return returnValue;
}
}
public sealed class InnerSampleObject : SampleObjectBase
{
}
public sealed class OuterSampleObject : SampleObjectBase
{
public InnerSampleObject DerivedSampleObject { get; set; }
}
我的问题是,在 SampleObjectBase 的注释代码中,我无法获取匹配的 PropertyInfo 值的具体实例。如果我查看循环中的 PropertyInfo 对象,我会发现类型是正确的,但我找不到直接访问实现中已存在的实例的方法。因此,例如,在执行 OuterSampleObject.IsValid() 时,代码会按预期找到 InnerSampleObject 的 PropertyInfo。我想执行 InnerSampleObject.IsValid()。
我已经尝试过(多种变体):
var childIsValid = (bool)contractProperty.PropertyType.InvokeMember("IsValid", BindingFlags.InvokeMethod, null, null, null);
并且:
var childInstance = (ISampleContract)contractProperty;
第一个的问题是我无法将 null 作为 InvokeMember 的目标传递,因为 IsValid() 不是静态的(也不能是静态的,因为我专注于实际情况)。第二个只是一个蹩脚的演员阵容,但却是我想要完成的要点。
上面的示例代码只是我想要实现的目标的一个极简示例。完整的代码是自验证 DTO 的一部分,它递归地检查整个层次结构并返回哪些子项存在验证问题以及它们是什么。
任何帮助将不胜感激。
I have been struggling a bit with some reflection code that I though would be simple. Essentially, I have an interface that defines a method. Then, I have an abstract class that provides a base implementation of that method.
The concrete classes can contain nested instances of other classes that can also derive from the same base class. It can be illustrated by the following sample:
using System.Linq;
public interface ISampleObject
{
bool IsValid();
}
public abstract class SampleObjectBase : ISampleObject
{
public bool IsValid()
{
var returnValue = true;
// Self-validation sets the return value.
var childProperties = this.GetType().GetProperties().Where(pi => typeof(ISampleObject).IsAssignableFrom(pi.PropertyType));
foreach (var childProperty in childProperties)
{
// var childInstance = ????; // Need the actual *existing* instance property, cast to ISampleObject.
// if (childInstance.IsValid() != true)
// {
// returnValue = false;
// }
}
return returnValue;
}
}
public sealed class InnerSampleObject : SampleObjectBase
{
}
public sealed class OuterSampleObject : SampleObjectBase
{
public InnerSampleObject DerivedSampleObject { get; set; }
}
My problem is that in the commented code for SampleObjectBase, I cannot get the concrete instance of the matching PropertyInfo value. If I look at the PropertyInfo object in the loop, I see that the type is correct, but I cannot find a way to directly access the instance that already exists in the implementation. So, when executing, for example, OuterSampleObject.IsValid(), the code finds the PropertyInfo for InnerSampleObject, as expected. I want to execute InnerSampleObject.IsValid().
I have tried (multiple variations of):
var childIsValid = (bool)contractProperty.PropertyType.InvokeMember("IsValid", BindingFlags.InvokeMethod, null, null, null);
And:
var childInstance = (ISampleContract)contractProperty;
The problem with the first one is that I can't pass null in as the target for InvokeMember, as IsValid() is not static (nor can it be, since I am focused on the actual instance). The second on is just a lame cast, but is the gist of what I want to accomplish.
The sample code above is just a minimalist example of what I want to achieve. The full code is part of a self-validating DTO that recursively checks the entire hierarchy and returns what children have validation issues and what they are.
Any help would be greatly appreciated.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
怎么样:
How about:
请查看下面的代码是否是您要查找的内容。我的更改标有以
//VH:
开头的注释Please see if the code below is what you are looking for. My changes are marked with a comment starting with
//VH:
只需使用
Just use