【问题标题】:Reflecting Over Nested Instances without Creating New Instance反射嵌套实例而不创建新实例
【发布时间】:2011-05-07 13:01:05
【问题描述】:

我一直在为一些我认为很简单的反射代码而苦苦挣扎。本质上,我有一个定义方法的接口。然后,我有一个提供该方法的基本实现的抽象类。

具体类可以包含其他类的嵌套实例,这些实例也可以派生自同一个基类。可以用下面的例子来说明:

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

任何帮助将不胜感激。

【问题讨论】:

  • 看起来你的returnValue 永远不可能是true
  • 只是一个错字。不过,已修复。 ;-)

标签: c# reflection system.reflection


【解决方案1】:

怎么样:

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

【讨论】:

  • 哦,天哪...我以为我曾经尝试过一次并得到了 StackOverflowException。我希望我有旧版本来看看我实际上做了什么,但这很好用。 :-)
【解决方案2】:

请查看下面的代码是否是您要查找的代码。我的更改标有以 //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();

    }
}

【讨论】:

    【解决方案3】:

    随便用

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

    【讨论】:

      猜你喜欢
      • 2015-03-01
      • 1970-01-01
      • 1970-01-01
      • 2018-08-03
      • 2016-03-02
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多