2

式ツリーを構築しようとしていますが、コンパイル時に NotSupportedException がスローされます。

TryExpression はメソッド 'Boolean TryGetMemberValue(System.Object, System.String, System.Object ByRef)' の引数としてサポートされていません。TryExpression がこの式内にネストされないようにツリーを構築します。

私はそれが言っていることをある程度理解していますが、何を変更する必要があるのか​​\u200b\u200bわかりません...コードは次のとおりです。

static void Main()
{
    //A.Child.Name
    var child = CreateExpression("Child", proxyParameter);
    var name = CreateExpression("Name", child);

    var expr = Expression.Lambda<Func<Proxy, object>>(name, proxyParameter);

    var func = expr.Compile();
}

class A
{
    public A Child { get; set; }
    public string Name { get; set; }
}

abstract class Proxy
{
    public abstract bool TryGetMemberValue(object parent, string name, out object result);
}

static ParameterExpression proxyParameter = Expression.Parameter(typeof(Proxy), "proxy");

static Expression CreateExpression(string propertyName, Expression parent)
{
    var tryGetMemberMethod = typeof(Proxy).GetMethod("TryGetMemberValue");

    var result = Expression.Variable(typeof(object), "out result");

    var returnTarget = Expression.Label(typeof(object));

    var tryGetMember =
        Expression.Block(
            new[] { result },
            Expression.IfThenElse(Expression.Equal(Expression.Call(proxyParameter, tryGetMemberMethod, parent, Expression.Constant(propertyName), result), Expression.Constant(true)),
                Expression.Return(returnTarget, result),
                Expression.Throw(Expression.Constant(new MissingMemberException(propertyName)))),
            Expression.Label(returnTarget, Expression.Constant(null)));

    return tryGetMember;
}

これにより、次の式が生成されます。

.Lambda #Lambda1<System.Func`2[Program+Proxy,System.Object]>(Program+Proxy $proxy) {
.Block(System.Object $'out result') {
    .If (.Call $proxy.TryGetMemberValue(
        .Block(System.Object $'out result') {
            .If (.Call $proxy.TryGetMemberValue(
                $proxy,
                "Child",
                $'out result') == True) {
                .Return #Label1 { $'out result' }
            } .Else {
                .Throw .Constant<System.MissingMemberException>(System.MissingMemberException: Child)
            };
            .Label
                null
            .LabelTarget #Label1:
        },
        "Name",
        $'out result') == True) {
        .Return #Label2 { $'out result' }
    } .Else {
        .Throw .Constant<System.MissingMemberException>(System.MissingMemberException: Name)
    };
    .Label
        null
    .LabelTarget #Label2:
}

何か案は?

/*編集済み*/興味深いことに、これはうまく機能します:

var tryGetMember =
    Expression.Block(
        new[] { result },
        Expression.Call(proxyParameter, tryGetMemberMethod, parent, Expression.Constant(propertyName), result),
    result);
4

1 に答える 1