1

我一直在努力使用一些我认为很简单的反射代码。本质上,我有一个定义方法的接口。然后,我有一个抽象类,它提供了该方法的基本实现。

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

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 的一部分,它递归地检查整个层次结构并返回哪些子级存在验证问题以及它们是什么。

任何帮助将不胜感激。

4

3 回答 3

2

怎么样:

var instance = childProperty.GetValue(this, null) as ISampleObject;
if (instance != null)
{
  if (!instance.IsValid())
    return false;
}
于 2011-05-07T13:40:50.517 回答
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();

    }
}
于 2011-05-07T13:34:45.473 回答
1

只需使用

var childInstance = (ISampleObject)childProperty.GetValue(this, null);
于 2011-05-07T13:35:29.283 回答