在不创建新实例的情况下反映嵌套实例

时间:2011-05-07 13:01:06

标签: c# reflection system.reflection

我一直在用一些反射代码挣扎,但我会很简单。基本上,我有一个定义方法的接口。然后,我有一个抽象类,它提供了该方法的基本实现。

具体类可以包含其他类的嵌套实例,这些实例也可以派生自相同的基类。可以通过以下示例进行说明:

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的一部分,它以递归方式检查整个层次结构,并返回子项验证问题及其内容。

非常感谢任何帮助。

3 个答案:

答案 0 :(得分:2)

怎么样:

var instance = childProperty.GetValue(this, null) as ISampleObject;
if (instance != null)
{
  if (!instance.IsValid())
    return false;
}

答案 1 :(得分:1)

请查看以下代码是否符合您的要求。我的更改标有以//VH:

开头的评论
public interface ISampleObject
{
    bool IsValid();
}

public abstract class SampleObjectBase : ISampleObject
{
    public virtual bool IsValid()
    {
        var returnValue = true; //VH: Changed value from false to true

        // Self-validation sets the return value.

        var childProperties = this.GetType().GetProperties().Where(pi => typeof(ISampleObject).IsAssignableFrom(pi.PropertyType));

        foreach (var childProperty in childProperties)
        {
            //VH: Here is how you get the value of the property
            var childInstance = (ISampleObject)childProperty.GetValue(this, null);
            if (childInstance.IsValid() != true)                
            {
                 returnValue = false;
            }
        }

        return returnValue;
    }
}

public sealed class InnerSampleObject : SampleObjectBase
{
}

public sealed class OuterSampleObject : SampleObjectBase
{
    //VH: Added this constructor
    public OuterSampleObject()
    {
        DerivedSampleObject = new InnerSampleObject();
    }

    public InnerSampleObject DerivedSampleObject { get; set; }
}


class Program
{
    static void Main(string[] args)
    {
        OuterSampleObject c = new OuterSampleObject();
        c.IsValid();

    }
}

答案 2 :(得分:1)

只需使用

var childInstance = (ISampleObject)childProperty.GetValue(this, null);