Expression .Dynamic and Operators.Assign?

I am trying to use Expression.Dynamic () to create an assignment operation ... I want to use this to selectively suggest value type semantics to certain instances of a special type in my language. I can't do this with a "static" (?) Expression because I don't know what the actual type is (I need a MetaObject instance and its LimitType ... hence Expression.Dynamic ()).

It doesn't work for me ... Expression.Assign () does nothing when used to create a MetaObject from my OperationBinder subclass.

Chapter. Knock. On the. Desk. For. Clock.

Just wondering if this is supported by a supported behavior, or if I'm barking the wrong tree?

Thank...

0


source to share


3 answers


I think you basically have 2 options. Either way though, you should use a custom binder instead of subclassing OperationBinder. This is because you are not doing cross-language mode. Instead, you implement some of your language semantics, but you just want some good DLR stuff. You must subclass the MetaObjectBinder class for this to happen (MetaAction in older assemblies).

So, your two options should either have Ast.Dynamic, which returns the new value you are assigning to local, or pass the value as a ref argument. They should look like this:

Ast.Assign(localVal, Ast.Dynamic(new AssignBinder(...), localVal, newVal);

or

delegate void AssignDelegate<TLocal, TValue>(CallSite site, TLocal loc, TValue val);
Type dlgType = typeof(AssignDelegate).MakeGenericType(new Type[] { localVal.Type, newVal.Type });
Ast.Dynamic(dlgType, new AssignBinder(...), localVal, newVal);

      



In your binder, you will override the Bind method, which will give you the incoming MetaObject. For the former, you will simply return a new value, and the latter only for the first metaobject.

I haven't tried this, but basically how it should work.

+3


source


Can you elaborate on the exact scenario? I am very familiar with Expression

and readily familiar with its use of DLR tree / 4.0, but I am not 100% sure what you are trying to do. Note also that there are limitations with this type of use anyway (be it C # or raw trees).



0


source


If you want to create an assignment expression, just create an expression that calls the general assignment procedure. The class below provides a nice extension method that converts any field access expression to a field assignment expression:

using System;
using System.Linq.Expressions;
using System.Reflection;

namespace Ethica.Expressions
{
    public static class ExpressionExtenstions
    {
        private class AssignmentHelper<T>
        {
            private static void SetValue(ref T target, T value)
            {
                target = value;
            }

            internal static MethodInfo MethodInfoSetValue =
                typeof(AssignmentHelper<T>).GetMethod("SetValue", BindingFlags.NonPublic | BindingFlags.Static);
        }


        public static Expression<Action<TInstance, TProp>> ToFieldAssignExpression<TInstance, TProp>
            (
                this Expression<Func<TInstance, TProp>> fieldGetter
            )
        {
            if (fieldGetter == null)
                throw new ArgumentNullException("fieldGetter");

            if(fieldGetter.Parameters.Count != 1 || !(fieldGetter.Body is MemberExpression))
                throw new ArgumentException ("Input expression must be a single parameter field getter, e.g. g => g._fieldToSet  or function(g) g._fieldToSet");

            ParameterExpression[] parms = new ParameterExpression[] {
                                        fieldGetter.Parameters[0], 
                                        Expression.Parameter(typeof(TProp), "value")};

            Expression body = Expression.Call(AssignmentHelper<TProp>.MethodInfoSetValue,
                                              new Expression[] { fieldGetter.Body, parms[1] });

            return Expression.Lambda<Action<TInstance, TProp>>(body, parms);
        }


        public static Action<TInstance, TProp> ToFieldAssignment<TInstance, TProp>
            (
                this Expression<Func<TInstance, TProp>> fieldGetter
            )
        {
            return fieldGetter.ToFieldAssignExpression().Compile();
        }
    }
}

      

0


source







All Articles