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;

最初のものの問題は、IsValid()が静的ではないため(実際のインスタンスに焦点を合わせているため、静的ではないため)、InvokeMemberのターゲットとしてnullを渡すことができないことです。2つ目は単なるラメキャストですが、私が達成したいことの要点です。

上記のサンプルコードは、私が達成したいことの最小限の例にすぎません。完全なコードは、階層全体を再帰的にチェックし、検証の問題がある子とその子を返す自己検証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 に答える