0

次のような式が与えられた場合:

m => m.Employee.Address.Line1

関係するオブジェクトを引き出したり、少なくともチェーンの最後のオブジェクト (つまり、上記の Address オブジェクト) を取り出したりして、式をたどることができる関数を作成する必要があります。したがって、上記の例では、関数は次のことを見つけます。

  • 「ここ」は m パラメーターのインスタンスです (そこから型を取得できます)
  • 「ここ」は従業員メンバーのインスタンスです
  • (つまり、チェーンを下に繰り返します)

その目的は、「パス」の構成情報を生成できるようにすることです。

少なくとも最終的な「包含」オブジェクトを取得できれば、型情報を生成できるだけでなく、オブジェクトが特定の属性またはメソッドをサポートしている場合はそのオブジェクトを呼び出して、オブジェクト (および取得するオブジェクト Type) から追加の構成情報を要求することもできます。コンテナのタイプの構成情報)。

次のような少し複雑なステートメントでも、これはさらに難しくなります。

m.Employee.Address[i].Line1

--- MVC の BASIC シナリオで私が行っていることのサンプルを提供するだけです。以下の GetContainingModel() は、読み込まれた DataAnnotationsMetadataProvider の CreateMetadata() 内で呼び出されます。CreateMetadata() に渡されるモデルは、Lambda ステートメントの ROOT にあるモデルであり、実際に必要なものではありません。そのため、ロジックは最終的な包含オブジェクトを見つけようとします。私が行っているようにリフレクションを使用したくない、またはさらに悪いことに、プライベートメンバーを取得するために手を差し伸べる(悪い)が、...私は提案を求めています。

    [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
    private object GetContainingModel()
    {
        if (_metadata == null)
        {
            throw new SystemException("Unexpected NULL Metadata");
        }

        var model = _metadata.Model;

        try
        {
            if (_modelAccessor != null)
            {
                var data = _modelAccessor.Target;
                if (data != null)
                {
                    if (GetModelFromContainer(data, ref model))
                    {
                        GetModelFromExpression(data, ref model);
                    }
                }
            }
        }
        catch (Exception ex)
        {
            var msg = ex.Message;
        }

        return model;
    }

    [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
    private bool GetModelFromContainer(object data, ref object model)
    {
        var isSet = false;

        var container = data.GetType().GetField("container");
        if (container != null)
        {
            model = container.GetValue(data);
            isSet = true;
        }
        else
        {
            var vdi = data.GetType().GetField("vdi");
            if (vdi != null)
            {
                var viewDataInfo = vdi.GetValue(data) as ViewDataInfo;
                if (viewDataInfo != null)
                {
                    model = viewDataInfo.Container;
                    isSet = true;
                }
            }
        }

        return isSet && model != null;
    }

    [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
    private bool GetModelFromExpression(object data, ref object model)
    {
        if (model == null)
            return false;

        var expressionField = data.GetType().GetField("expression");
        if (expressionField == null)
            return false;

        return GetModelFromExpression(expressionField.GetValue(data) as LambdaExpression, ref model);
    }

    [TargetedPatchingOptOut("Performance critical to inline this type of method across NGen image boundaries")]
    private bool GetModelFromExpression(LambdaExpression sourceExpression, ref object model)
    {
        if (sourceExpression == null)
            return false;

        var expressionBody = sourceExpression.Body as MemberExpression;

        if (expressionBody == null || expressionBody.NodeType != ExpressionType.MemberAccess || expressionBody.Member == null)
            return false;


        var expression = expressionBody.Expression as MemberExpression;
        if (expression == null)
        {
            return false;
        }

        switch (expression.Member.MemberType)
        {
            case MemberTypes.Field:
                if (expression.NodeType == ExpressionType.MemberAccess)
                {
                    var fieldInfo = (FieldInfo)expression.Member;
                    if (fieldInfo != null)
                    {
                        model = fieldInfo.GetValue(model);
                    }
                }
                break;
            case MemberTypes.Property:
                var propertyInfo = (PropertyInfo)expression.Member;
                if (propertyInfo != null)
                {
                    model = propertyInfo.GetValue(model, null);
                }
                break;
        }

        return model != null;
    }
4

0 に答える 0