Esempio n. 1
0
            public Updater(Type type)
            {
                var props = from p in type.GetProperties()
                            let bas                 = p.GetCustomAttributes(typeof(BrowsableAttribute), true)
                                              let b = bas.FirstOrDefault() as BrowsableAttribute
                                                      where p.CanWrite && (b == null || b.Browsable)
                                                      select p;

                var convert = typeof(Updater).GetMethod("FromString", BindingFlags.Static | BindingFlags.NonPublic);

                foreach (var p in props)
                {
                    var instance = X.Parameter(typeof(object));
                    var value    = X.Parameter(typeof(string));

                    var lambda = X.Lambda <Action <object, string> >(
                        X.Assign(
                            X.Property(
                                X.Convert(instance, type),
                                p
                                ),
                            X.Convert(
                                X.Call(convert, value, X.Constant(p.PropertyType)),
                                p.PropertyType
                                )
                            ),
                        instance, value);

                    cache[p.Name] = lambda.Compile();
                }
            }
Esempio n. 2
0
        public override MSAst TransformCore(ScriptGenerator generator)
        {
            var scope = generator.PushNewScope();

            try
            {
                for (int i = 0; i < _scope.Parameters.Count; i++)
                {
                    _scope.Parameters[i].Transform(generator);
                }


                var transformedBody = _body.Transform(generator);

                if ((ReturnType != null) && (ReturnType != TypeManager.CoreTypes.Object) && (transformedBody.Type != ReturnType))
                {
                    transformedBody = MSAst.Convert(transformedBody, ReturnType);
                }

                var result = scope.FinishScope(transformedBody);

                return(result);
            }
            finally
            {
                generator.PopScope();
            }
        }
Esempio n. 3
0
 /// <summary>
 /// Return true if the object is in the given circle relative to a BehaviorEntity.
 /// </summary>
 /// <param name="beh">Target BehaviorEntity</param>
 /// <param name="circ">Relative circle</param>
 /// <returns></returns>
 public static ExPred RelCirc(BEHPointer beh, ExTP3 circ)
 {
     return(bpi => CollisionMath.pointInCircle.Of(
                Ex.Subtract(bpi.loc, LBEH(beh)),
                Ex.Convert(circ(bpi), typeof(CCircle))
                ));
 }
        static GlyphRunFormatter()
        {
            var refType = typeof(CharacterBufferReference);

            _textFormattingMode = typeof(GlyphRun).GetField("_textFormattingMode", BindingFlags.NonPublic | BindingFlags.Instance);

            {
                var property = refType.GetProperty("CharacterBuffer", BindingFlags.NonPublic | BindingFlags.Instance);
                var param0   = Expr.Parameter(refType);
                var expr     = Expr.Convert(Expr.Property(param0, property), typeof(IList <char>));
                var lambda   = Expr.Lambda <Func <CharacterBufferReference, IList <char> > >(expr, param0);
                getCharBuf = lambda.Compile();
            }

            {
                var property = refType.GetProperty("OffsetToFirstChar", BindingFlags.NonPublic | BindingFlags.Instance);
                var param0   = Expr.Parameter(refType);
                var expr     = Expr.Property(param0, property);
                var lambda   = Expr.Lambda <Func <CharacterBufferReference, int> >(expr, param0);
                getCharOffset = lambda.Compile();
            }

            {
                var ctor   = typeof(TextBounds).GetConstructors(BindingFlags.NonPublic | BindingFlags.Instance)[0];
                var param0 = Expr.Parameter(typeof(Rect));
                var expr   = Expr.New(ctor, param0, Expr.Constant(FlowDirection.LeftToRight), Expr.Constant(null, typeof(IList <TextRunBounds>)));
                var lambda = Expr.Lambda <Func <Rect, TextBounds> >(expr, param0);
                makeBounds = lambda.Compile();
            }
        }
Esempio n. 5
0
            static Expr GenerateAddFlagsGuts(ExprParam paramV, ExprParam paramF)
            {
                var v_as_int = Expr.Convert(paramV, kUnderlyingType);                                           // integer v = (integer)value
                var f_as_int = Expr.Convert(paramF, kUnderlyingType);                                           // integer f = (integer)flags

                return(Expr.Convert(Expr.Or(v_as_int, f_as_int), kEnumType));                                   // (TEnum)(v | f)
            }
        public override DynamicMetaObject FallbackUnaryOperation(DynamicMetaObject target, DynamicMetaObject errorSuggestion)
        {
            if (!target.HasValue)
            {
                return(Defer(target));
            }

            DynamicMetaObject firstVarargs;

            if (RuntimeHelpers.TryGetFirstVarargs(target, out firstVarargs))
            {
                return(FallbackUnaryOperation(firstVarargs, errorSuggestion));
            }

            Expr expression;

            switch (Operation)
            {
            case ExprType.Negate:
                expression = NegateOp(target);
                break;

            case ExprType.Not:
                expression = NotOp(target);
                break;

            default:
                throw new ArgumentOutOfRangeException();
            }

            return(new DynamicMetaObject(Expr.Convert(expression, typeof(object)), RuntimeHelpers.MergeTypeRestrictions(target)));
        }
Esempio n. 7
0
        public override (Expression, ExpressionConversionResult) Convert(ArrayExpression node, ExpressionConverterContext expressionConverterContext, ExpressionConverterScope expressionConverterScope, bool allowTerminal, params Type[] genericArguments)
        {
            if (expressionConverterScope.TargetType == typeof(JArray))
            {
                var code = expressionConverterContext.Source.Substring(node.Range.Start, node.Range.End - node.Range.Start + 1);
                using (var reader = new StringReader(code)) {
                    var @object = JsonSerializer.Deserialize(reader, expressionConverterScope.TargetType);
                    return(Expression.Constant(@object), DefaultResult);
                }
            }
            var targetType = expressionConverterScope.TargetType != null?expressionConverterScope.TargetType.GetEnumerableUnderlyingType() : null;

            var itemScope           = new ExpressionConverterScope(expressionConverterScope, targetType);
            var elementsExpressions = node.Elements.Select((element, index) => {
                var itemExpression = expressionConverterContext.ExpressionConverterResolver.Convert(element, expressionConverterContext, itemScope, allowTerminal);
                if (index == 0 && targetType == null)
                {
                    targetType = itemExpression.Type;
                }
                if (itemExpression.Type != targetType && targetType != null)
                {
                    itemExpression = Expression.Convert(itemExpression, targetType);
                }
                return(itemExpression);
            }).ToArray();

            return(Expression.NewArrayInit(targetType, elementsExpressions), DefaultResult);
        }
Esempio n. 8
0
        public static List <T> FilterAndOrder <T>(IQueryable <T> records, T filters, string sortColumnName, string sortOrder)
        {
            var filterDict = new Dictionary <string, string>();
            var fields     = typeof(T).GetProperties(BindingFlags.Public | BindingFlags.Instance);
            var keyField   = fields.First();

            foreach (var field in fields)
            {
                var filterValue            = field.GetMethod.Invoke(filters, new object[0]);
                var filterTypeDefaultValue = field.PropertyType.GetDefaultValue();
                if (filterValue != null &&
                    (filterTypeDefaultValue == null || filterValue.ToString() != filterTypeDefaultValue.ToString()))
                {
                    filterDict.Add(field.Name, filterValue.ToString());
                }
            }
            SearchPackage searchPackage = jqGridHelper.GetExportSearchPackage(filterDict, sortColumnName, sortOrder);

            var dataBuilder  = new SearchPackageDataBuilder <T>(searchPackage, records);
            var param        = Expression.Parameter(typeof(T), "r");
            var keyFieldExpr =
                Expression.Lambda <Func <T, object> >(
                    Expression.Convert(Expression.Property(param, keyField), typeof(object)),
                    param);
            var sortFieldExpr =
                Expression.Lambda <Func <T, object> >(
                    Expression.Convert(Expression.Property(param, sortColumnName ?? keyField.Name), typeof(object)),
                    param);

            return(dataBuilder
                   .Map(keyFieldExpr, r => fields.Select(f => f.GetMethod.Invoke(r, new object[0])).ToArray())
                   .GetExportResult(sortFieldExpr));
        }
Esempio n. 9
0
        public static Expression Call(ProcedureCall call)
        {
            if (ReferenceEquals(call, null))
            {
                throw new ArgumentNullException(nameof(call));
            }
            var services  = Services.Instance;
            var procedure = services.GetProcedureSignature(call);

            if (!procedure.HasReturnType)
            {
                throw new InvalidOperationException(
                          "Cannot use a procedure that does not return a value.");
            }
            var arguments = services.GetArguments(procedure, call.Arguments);

            var servicesExpr      = LinqExpression.Constant(services);
            var executeCallMethod = typeof(Services).GetMethod(
                "ExecuteCall", new[] { typeof(Scanner.ProcedureSignature), typeof(object[]) });
            var procedureExpr = LinqExpression.Constant(procedure);
            var argumentsExpr = LinqExpression.Constant(arguments);

            var result = LinqExpression.Call(
                servicesExpr, executeCallMethod,
                new[] { procedureExpr, argumentsExpr });
            var value = LinqExpression.Convert(
                LinqExpression.Property(result, "Value"), procedure.ReturnType);

            return(new Expression(value));
        }
Esempio n. 10
0
        internal static Func <TEnum, TInt> GenerateToMethod <TInt>()
        {
            // NOTE: Getting runtime errors in lambda.Compile() when we try to return value__ directly

            //////////////////////////////////////////////////////////////////////////
            // Define the generated method's parameters
            var param_v = GenerateParamValue();

#if false
            var param_v_member = Expr.PropertyOrField(param_v, EnumUtils.kMemberName);             // value.value__
#endif

            //////////////////////////////////////////////////////////////////////////
            // [result] = (TInt)value.value__
            var TIntType = typeof(TInt);
#if false
            var value_expr = TIntType != kUnderlyingType?
                             Expr.Convert(param_v_member, TIntType) :
                                 param_v_member as Expr;
#else
            var value_expr = Expr.Convert(param_v, TIntType);
#endif

            //////////////////////////////////////////////////////////////////////////
            // return (TInt)value.value__
            var ret = value_expr;

            var lambda = Expr.Lambda <Func <TEnum, TInt> >(ret, param_v);
            return(lambda.Compile());
        }
Esempio n. 11
0
        private static MSAst ConvertExpression(MSAst expr, Type toType)
        {
            if (expr == null)
            {
                throw new ArgumentNullException("expr");
            }
            if (toType == null)
            {
                throw new ArgumentNullException("toType");
            }

            var exprType = expr.Type;

            if (toType == typeof(object))
            {
                if (exprType.IsValueType)
                {
                    return(AstUtils.Convert(expr, toType));
                }
                return(expr);
            }

            if (toType.IsAssignableFrom(exprType))
            {
                return(expr);
            }

            //Type visType = CompilerHelpers.GetVisibleType(toType);

            return(MSAst.Convert(expr, toType));
        }
Esempio n. 12
0
 public static Expr UnaryMinus(Context context, DynamicMetaObject target)
 {
     return(Expr.Invoke(
                Expr.Constant((Func <Context, object, object>)LuaOps.UnaryMinusMetamethod),
                Expr.Constant(context, typeof(Context)),
                Expr.Convert(target.Expression, typeof(object))));
 }
Esempio n. 13
0
        /// <summary>Helper to produce the rule for converting T to Nullable of T</summary>
        private static MSAst MakeConvertingToTToNullableOfTTarget(Type toType, ConversionResultKind kind, MSAst arg)
        {
            var valueType = toType.GetGenericArguments()[0];

            // ConvertSelfToT -> Nullable<T>
            if (kind == ConversionResultKind.ExplicitCast)
            {
                // if the conversion to T fails we just throw
                var conversion = ConvertExpression(arg, valueType);

                return(MSAst.New(
                           toType.GetConstructor(new[] { valueType }),
                           conversion));
            }
            else
            {
                var conversion = ConvertExpression(arg, valueType);

                // if the conversion to T succeeds then produce the nullable<T>, otherwise return default(retType)

                return(MSAst.Condition(
                           MSAst.NotEqual(
                               conversion,
                               AstUtils.Constant(null)),
                           MSAst.New(
                               toType.GetConstructor(new[] { valueType }),
                               MSAst.Convert(
                                   conversion,
                                   valueType)),
                           GetTryConvertReturnValue(toType)));
            }
        }
Esempio n. 14
0
 public static Expr Index(Context context, DynamicMetaObject target, DynamicMetaObject[] indexes)
 {
     return(Expr.Invoke(
                Expr.Constant((Func <Context, object, object, object>)LuaOps.IndexMetamethod),
                Expr.Constant(context, typeof(Context)),
                Expr.Convert(target.Expression, typeof(object)),
                Expr.Convert(indexes[0].Expression, typeof(object))));
 }
Esempio n. 15
0
            static Expr GenerateRemoveFlagsGuts(ExprParam paramV, ExprParam paramF)
            {
                var v_as_int = Expr.Convert(paramV, kUnderlyingType);                                           // integer v = (integer)value
                var f_as_int = Expr.Convert(paramF, kUnderlyingType);                                           // integer f = (integer)flags

                var f_complement = Expr.Not(f_as_int);                                                          // ~f

                return(Expr.Convert(Expr.And(v_as_int, f_complement), kEnumType));                              // (TEnum)(v & ~f)
            }
Esempio n. 16
0
            public override DynamicMetaObject BindGetMember(GetMemberBinder binder)
            {
                var expression = Expr.Call(
                    Expr.Convert(Expression, typeof(LuaTable)),
                    MemberInfos.LuaTableGetValue,
                    Expr.Constant(binder.Name));

                return(new DynamicMetaObject(expression, RuntimeHelpers.MergeTypeRestrictions(this)));
            }
Esempio n. 17
0
 public static Expr BinaryOp(Context context, ExprType operation, DynamicMetaObject left, DynamicMetaObject right)
 {
     return(Expr.Invoke(
                Expr.Constant((Func <Context, ExprType, object, object, object>)LuaOps.BinaryOpMetamethod),
                Expr.Constant(context, typeof(Context)),
                Expr.Constant(operation),
                Expr.Convert(left.Expression, typeof(object)),
                Expr.Convert(right.Expression, typeof(object))));
 }
Esempio n. 18
0
        internal static Func <TInt, TEnum> GenerateFromMethod <TInt>()
        {
            var TIntType = typeof(TInt);
            var param_v  = Expr.Parameter(TIntType, "value");

            var ret = Expr.Convert(param_v, kEnumType);

            var lambda = Expr.Lambda <Func <TInt, TEnum> >(ret, param_v);

            return(lambda.Compile());
        }
Esempio n. 19
0
        static void GenerateFromMethod <TInt>(out Func <TInt, TEnum> func)
        {
            var TIntType = typeof(TInt);
            var param_v  = Expr.Parameter(TIntType, "value");

            var ret = Expr.Convert(param_v, kEnumType);

            var lambda = Expr.Lambda <Func <TInt, TEnum> >(ret, param_v);

            func = lambda.Compile();
        }
Esempio n. 20
0
        public static Expr Call(Context context, DynamicMetaObject target, DynamicMetaObject[] args)
        {
            var expression = Expr.Invoke(
                Expr.Constant((Func <Context, object, object[], object>)LuaOps.CallMetamethod),
                Expr.Constant(context, typeof(Context)),
                Expr.Convert(target.Expression, typeof(object)),
                Expr.NewArrayInit(
                    typeof(object),
                    args.Select(arg => Expr.Convert(arg.Expression, typeof(object)))));

            return(expression);
        }
Esempio n. 21
0
        /// <summary>
        /// 获取日期常量表达式
        /// </summary>
        /// <param name="value">日期值</param>
        /// <param name="targetType">目标类型</param>
        public static MicrosoftExpression CreateDateTimeExpression(object value, Type targetType)
        {
            var parse = typeof(DateTime).GetMethod("Parse", new[] { typeof(string) });

            if (parse == null)
            {
                return(null);
            }
            var parseExpression = MicrosoftExpression.Call(parse, MicrosoftExpression.Constant(value.SafeString()));

            return(MicrosoftExpression.Convert(parseExpression, targetType));
        }
Esempio n. 22
0
 private static Func <object, T> TryMakePropertyGetDelegate <T>(Type instanceType, string propertyOrField)
 {
     try
     {
         var obj  = Expression.Parameter(typeof(object), "o");
         var expr = Expression.Lambda <Func <object, T> >(Expression.Convert(Expression.PropertyOrField(Expression.Convert(obj, instanceType), propertyOrField), typeof(T)), obj);
         return(expr.Compile());
     }
     catch
     {
         return(null);
     }
 }
Esempio n. 23
0
 /// <summary>
 /// Builds a delegate that casts an object to a target type and then gets the value a property or field.
 /// </summary>
 /// <typeparam name="T">The expected return type of the property or field.</typeparam>
 /// <param name="targetType">The expected target instance type.</param>
 /// <param name="propertyOrField">The name of the target property or field.</param>
 /// <returns>A delegate.</returns>
 private static Func <object, T> TryMakePropertyGetFromObjectDelegate <T>(Type targetType, string propertyOrField)
 {
     try
     {
         var target = Expression.Parameter(typeof(object), "target");
         var expr   = Expression.Lambda <Func <object, T> >(Expression.Convert(Expression.PropertyOrField(Expression.Convert(target, targetType), propertyOrField), typeof(T)), target);
         return(expr.Compile());
     }
     catch
     {
         return(null);
     }
 }
Esempio n. 24
0
                }                 // ctor

                private DynamicMetaObject GetRawItemBinder()
                {
                    if (Value is TemplateSelectScope scope)
                    {
                        var rawItemExpression = LExpression.Property(LExpression.Convert(Expression, typeof(TemplateSelectScope)), nameof(RawItem));
                        var restriction       = BindingRestrictions.GetTypeRestriction(Expression, typeof(TemplateSelectScope));
                        return(new DynamicMetaObject(rawItemExpression, restriction, scope.RawItem));
                    }
                    else
                    {
                        throw new NotSupportedException();
                    }
                }                 // func GetRawItemBinder
Esempio n. 25
0
        public void Query_Where_Enum_AgainstDifferentEnumType_ManualExpression()
        {
            var lambda = BaseExpressionTest.CreateLambda(Property.Status, s =>
            {
                var retry      = Expr.Constant(RetryMode.Retry);
                var methodInfo = typeof(object).GetMethod(nameof(Equals), System.Reflection.BindingFlags.Static | System.Reflection.BindingFlags.Public);

                var method = Expr.Call(methodInfo, Expr.Convert(retry, typeof(object)), Expr.Convert(s, typeof(object)));

                return(method);
            });

            ExecuteFilter(lambda, string.Empty, s => Assert.AreEqual(0, s.Count));
        }
Esempio n. 26
0
        static ClientWindow()
        {
            var convertPixelMethod = typeof(SystemParameters).GetMethod(
                "ConvertPixel",
                BindingFlags.Static | BindingFlags.NonPublic);

            var pixelParameter = Expression.Parameter(typeof(double), "pixel");

            PixelToPoint = Expression.Lambda <Func <double, double> >(
                Expression.Call(
                    convertPixelMethod,
                    Expression.Convert(pixelParameter, typeof(int))),
                pixelParameter).Compile();
        }
Esempio n. 27
0
        public MSAst TransformClass()
        {
            var defaultContext = MSAst.Constant(null);
            var classFinders   = new List <MSAst>();

            foreach (var baseClass in BaseClasses)
            {
                classFinders.Add(MSAst.Lambda <Func <Class> >(MSAst.Convert(MSAst.Dynamic(GlobalParent.LanguageContext.CreateGetMemberBinder(baseClass, false), typeof(object), GlobalParent.Context), typeof(Class))));
            }
            var members = new Dictionary <string, MSAst>();

            foreach (var func in Functions)
            {
                members[func.Name] = func.TransformFunction(defaultContext);
            }
            foreach (var prop in Properties)
            {
                members[prop.Name] = prop.TransformProperty(defaultContext);
            }
            var membersArg = MSAst.Call(
                (System.Reflection.MethodInfo)Utils.GetMember(() => Enumerable.Zip <string, object, KeyValuePair <string, object> >(null, null, null)),
                MSAst.Constant(members.Keys),
                MSAst.NewArrayInit(typeof(object), members.Values),
                (System.Linq.Expressions.Expression <Func <string, object, KeyValuePair <string, object> > >)((x, y) => new KeyValuePair <string, object>(x, y))
                );
            var fields = new Dictionary <string, System.Linq.Expressions.Expression <Func <object, object> > >();

            foreach (var vd in VariableDeclarations)
            {
                foreach (var initializer in vd.Initializers)
                {
                    if (initializer.Value != null)
                    {
                        fields[initializer.Key] = MSAst.Lambda <Func <object, object> >(initializer.Value.TransformRead(), _context);
                    }
                    else
                    {
                        fields[initializer.Key] = MSAst.Lambda <Func <object, object> >(MSAst.Constant(Builtins.Void.Value), _context);
                    }
                }
            }
            var fieldsArg = MSAst.Call(
                (System.Reflection.MethodInfo)Utils.GetMember(() => Enumerable.Zip <string, Func <object, object>, KeyValuePair <string, Func <object, object> > >(null, null, null)),
                MSAst.Constant(fields.Keys),
                MSAst.NewArrayInit(typeof(Func <object, object>), fields.Values),
                (System.Linq.Expressions.Expression <Func <string, Func <object, object>, KeyValuePair <string, Func <object, object> > > >)((x, y) => new KeyValuePair <string, Func <object, object> >(x, y))
                );

            return(MSAst.New((System.Reflection.ConstructorInfo)Utils.GetMember(() => new Class(null, null, null, null)), MSAst.Constant(Name), MSAst.NewArrayInit(typeof(Func <Class>), classFinders), membersArg, fieldsArg));
        }
Esempio n. 28
0
        private static NodeVisitFunction BuildMethodVisitor(MethodInfo method, out Type parameterType)
        {
            var declaringtype = method.DeclaringType;

            if (declaringtype == null)
            {
                throw new InvalidOperationException(string.Format("No declaring type for method [{0}]", method.Name));
            }

            // Throws an exception if parammeters.Count != 1
            if (method.GetParameters().Length != 1)
            {
                throw new InvalidOperationException(
                          string.Format("Invalid number of parameters [{0}] for visit method [{1}] for type [{2}]. One parameter is expected", method.GetParameters().Length, method.Name, declaringtype.FullName));
            }

            parameterType = method.GetParameters()[0].ParameterType;
            if (!parameterType.IsInterface && !typeof(Node).IsAssignableFrom(parameterType))
            {
                throw new InvalidOperationException(
                          string.Format("Invalid type parameter [{0}] for visit method [{1}] for type [{2}]. Parameter must inherit from Node", parameterType, method.Name, declaringtype.FullName));
            }

            var thisParameter    = LinqExpression.Parameter(typeof(VisitorBase), "this");
            var nodeParameter    = LinqExpression.Parameter(typeof(object), "node");
            var thisCastVariable = LinqExpression.Variable(declaringtype, "thisCast");

            var statements = new List <LinqExpression>
            {
                LinqExpression.Assign(thisCastVariable, LinqExpression.Convert(thisParameter, declaringtype))
            };

            var callVisitMethod = LinqExpression.Call(thisCastVariable, method, LinqExpression.Convert(nodeParameter, parameterType));

            if (typeof(void) == method.ReturnType)
            {
                statements.Add(callVisitMethod);
                statements.Add(nodeParameter);
            }
            else
            {
                statements.Add(callVisitMethod);
            }

            var block = LinqExpression.Block(new[] { thisCastVariable }, statements);

            var lambda = LinqExpression.Lambda <NodeVisitFunction>(block, thisParameter, nodeParameter);

            return(lambda.Compile());
        }
Esempio n. 29
0
        /// <summary>
        /// Creates a function that takes the components of a composite search parameter as an
        /// enumerator and creates a ValueTuple with fields for each component.
        /// </summary>
        /// <returns>The generated function.</returns>
        private static Func <EnumeratorWrapper <ISearchValue>, TSearchValue> CreateConverterFunc()
        {
            var             parameter       = LinqExpression.Parameter(typeof(EnumeratorWrapper <ISearchValue>));
            MethodInfo      nextValueMethod = parameter.Type.GetMethod(nameof(EnumeratorWrapper <ISearchValue> .NextValue));
            ConstructorInfo constructorInfo = typeof(TSearchValue).GetConstructors().Single();

            return(LinqExpression.Lambda <Func <EnumeratorWrapper <ISearchValue>, TSearchValue> >(
                       LinqExpression.New(
                           constructorInfo,
                           constructorInfo.GetParameters().Select(p => LinqExpression.Convert(
                                                                      LinqExpression.Call(parameter, nextValueMethod),
                                                                      p.ParameterType))),
                       parameter).Compile());
        }
Esempio n. 30
0
        /// <summary>Generates a method similar to this:
        /// <code>
        /// void Write(IO.BitStream s, TEnum v, int bitCount)
        /// {
        ///     s.Write((TStreamType)v, bitCount);
        /// }
        /// </code>
        /// </summary>
        /// <returns>The generated method.</returns>
        /// <param name="args"></param>
        /// <param name="writeMethodInfo"></param>
        /// <param name="bitSwapMethod"></param>
        /// <remarks>
        /// If <see cref="args.UnderlyingType"/> is the same as <typeparamref name="TStreamType"/>, no conversion code is generated
        /// </remarks>
        static Action <IO.BitStream, TEnum, int> GenerateWriteMethod(MethodGenerationArgs args, MethodInfo writeMethodInfo, MethodInfo bitSwapMethod)
        {
            //////////////////////////////////////////////////////////////////////////
            // Define the generated method's parameters
            var param_s  = Expr.Parameter(kBitStreamType, "s");                                                         // BitStream s
            var param_v  = Expr.Parameter(args.EnumType, "v");                                                          // TEnum v
            var param_bc = Expr.Parameter(typeof(int), "bitCount");                                                     // int bitCount

            //////////////////////////////////////////////////////////////////////////
            // Define the member access
            var param_v_member = Expr.PropertyOrField(param_v, EnumUtils.kMemberName);                  // i.e., 'v.value__'
            var write_param    = args.UnderlyingTypeNeedsConversion ?                                   // If the underlying type is different from the type we're writing,
                                 Expr.Convert(param_v_member, args.StreamType) :                        // we need to cast the Write param from UnderlyingType to TStreamType
                                 (Expr)param_v_member;

            if (args.Options.UseNoneSentinelEncoding)
            {
                write_param = Expr.Increment(write_param);
            }

            #region options.BitSwap
            if (args.Options.BitSwap)
            {
                // i.e., Bits.BitSwap( value, bitCount-1 );
                var  start_bit_index = Expr.Decrement(param_bc);
                Expr swap_call       = Expr.Call(null, bitSwapMethod, write_param, start_bit_index);

                // i.e., bitCount-1 ? Bits.BitSwap( value, bitCount-1 ) : value ;
                if (args.Options.BitSwapGuardAgainstOneBit)
                {
                    var start_bit_index_is_not_zero = Expr.NotEqual(start_bit_index, Expr.Constant(0, typeof(int)));
                    swap_call = Expr.Condition(start_bit_index_is_not_zero,
                                               swap_call, write_param);
                }

                write_param = swap_call;
            }
            #endregion

            //////////////////////////////////////////////////////////////////////////
            // Define the Write call
            // i.e., 's.Write(v.value__, bitCount)' or 's.Write((TStreamType)v.value__, bitCount)'
            var call_write = Expr.Call(param_s, writeMethodInfo, write_param, param_bc);

            //////////////////////////////////////////////////////////////////////////
            // Generate a method based on the expression tree we've built
            var lambda = Expr.Lambda <Action <IO.BitStream, TEnum, int> >(call_write, param_s, param_v, param_bc);
            return(lambda.Compile());
        }