Example #1
0
        internal FieldInfo GetDynamicConvertBinder(Type type, Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags flags)
        {
            FieldInfo field;
            Tuple <Type, Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags> key = new Tuple <Type, Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags>(type, flags);

            this.ConvertBinders.TryGetValue(key, out field);
            if (field != null)
            {
                return(field);
            }

            string nameSuggestion = String.Format("{0}_{1}", flags, type.Name).Replace(" ", "").Replace("|", "_").Replace(",", "_");
            string name           = nameSuggestion;

            for (int i = 1; ; i++)
            {
                if (!this.ConvertBinders.Values.Any(f => f.Name == name))
                {
                    break;
                }
                name = String.Format("{0}_{1}", nameSuggestion, i);
            }

            field = this.ConvertBinderType.DefineField(name,
                                                       typeof(ConvertBinder),
                                                       FieldAttributes.Static | FieldAttributes.InitOnly | FieldAttributes.Assembly);

            this.ConvertBinders.Add(key, field);
            return(field);
        }
        public Expression CompileDynamicConvert(CompilationContext context, Expression parameter, Type type, ExpressionCompiler.Primitives.Conversion conversion)
        {
            // This is the tricky part ....
            //
            // Example that will NOT WORK:
            //      Int16 i16 = 123;
            //      Object o16 = i16;
            //      Int32 i32 = (Int32) o16     // *** FAILS *** ... even if object currently has an Int16, it's an object and no cast to Int32!
            //
            // Example that works:
            //      Int16 i16 = 123;
            //      Object o16 = i16;
            //      Int32 i32 = (Int16) o16     // OK! First cast Object=>Int16 then IMPLICIT cast Int16=>Int32
            //
            // VERY IMPORTANT!!!!
            //      This should ONLY do implicit conversion AND NO EXPLICIT conversions.
            //      If we do explicit conversion, we are screwed because the value
            //      will loose precision - and this is critical show stopper!
            //
            // C# Pseudocode Example ... cast to Int32:
            //      if (obj is Int32)
            //          return (Int32) obj;
            //      else
            //          return (Int32) ((dynamic) obj);     // This uses a CallSite and a C# CallSiteBinder to do the cast.
            //
            // The DLR does not provide an easy helper function. So we have two options:
            //  1. Write the logic for what converts implicitly to what (incl. dynamic cast). Too much work currently.
            //  2. Use the C# binder to do the work. We actually WANT the same semantics as C#, so that's OK. But we depend on them :-/

            Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags flags = Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags.None;
            if ((conversion & Conversion.Checked) == Conversion.Checked)
            {
                flags = flags | Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags.CheckedContext;
            }
            if ((conversion & Conversion.Explicit) == Conversion.Explicit)
            {
                flags = flags | Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags.ConvertExplicit;
            }
            // Create a C# convert binder. Currently, this is not cached, but we could do this in the future.
            ConvertBinderDefinition binder = new ConvertBinderDefinition(this.Client.Compiler.GetDynamicConvertBinder(type, flags));
            // Create a call site
            Type delegateType = typeof(Func <, ,>).MakeGenericType(typeof(CallSite), parameter.Type, type);
            Type siteType     = typeof(CallSite <>).MakeGenericType(delegateType);

            Expression callSite = this.CallSiteGenerator.CreateCallSite(binder, delegateType, siteType, String.Format("({0})", type.Name));

            FieldInfo  target = TypeUtilities.Field(siteType, "Target", BindingFlags.Instance | BindingFlags.Public);
            MethodInfo invoke = TypeUtilities.Method(delegateType, "Invoke");

            // siteExpr.Target.Invoke(siteExpr, parameter)
            return(Expression.Call(
                       Expression.Field(callSite, target),
                       invoke,
                       callSite, parameter));
        }
Example #3
0
        public Expression CompileDynamicConvert(CompilationContext context, Expression parameter, Type type, Primitives.Conversion conversion)
        {
            // This is the tricky part ....
            //
            // Example that will NOT WORK:
            //      Int16 i16 = 123;
            //      Object o16 = i16;
            //      Int32 i32 = (Int32) o16     // *** FAILS *** ... even if object currently has an Int16, it's an object and no cast to Int32!
            //
            // Example that works:
            //      Int16 i16 = 123;
            //      Object o16 = i16;
            //      Int32 i32 = (Int16) o16     // OK! First cast Object=>Int16 then IMPLICIT cast Int16=>Int32
            //
            // VERY IMPORTANT!!!!
            //      This should ONLY do implicit conversion AND NO EXPLICIT conversions.
            //      If we do explicit conversion, we are screwed because the value
            //      will loose precision - and this is critical show stopper!
            //
            // C# Pseudocode Example ... cast to Int32:
            //      if (obj is Int32)
            //          return (Int32) obj;
            //      else
            //          return (Int32) ((dynamic) obj);     // This uses a CallSite and a C# CallSiteBinder to do the cast.
            //
            // The DLR does not provide an easy helper function. So we have two options:
            //  1. Write the logic for what converts implicitly to what (incl. dynamic cast). Too much work currently.
            //  2. Use the C# binder to do the work. We actually WANT the same semantics as C#, so that's OK. But we depend on them :-/

            Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags flags = Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags.None;
            if ((conversion & Conversion.Checked) == Conversion.Checked)
            {
                flags = flags | Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags.CheckedContext;
            }
            if ((conversion & Conversion.Explicit) == Conversion.Explicit)
            {
                flags = flags | Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags.ConvertExplicit;
            }
            // Create a C# convert binder. Currently, this is not cached, but we could do this in the future.
            Tuple <Type, Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags> key = new Tuple <Type, Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags>(type, flags);
            ConvertBinder binder = DynamicCallStrategy.ConvertBinders.GetOrAdd(key, k => (ConvertBinder)Microsoft.CSharp.RuntimeBinder.Binder.Convert(k.Item2, k.Item1, typeof(DynamicCallStrategy)));
            // Create a call site
            Type delegateType = typeof(Func <, ,>).MakeGenericType(typeof(CallSite), parameter.Type, type);

            return(Expression.MakeDynamic(delegateType, binder, parameter));
        }
Example #4
0
 public static System.Runtime.CompilerServices.CallSiteBinder UnaryOperation(Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags flags, System.Linq.Expressions.ExpressionType operation, System.Type context, System.Collections.Generic.IEnumerable <Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo> argumentInfo)
 {
     throw null;
 }
Example #5
0
 public static System.Runtime.CompilerServices.CallSiteBinder SetMember(Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags flags, string name, System.Type context, System.Collections.Generic.IEnumerable <Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo> argumentInfo)
 {
     throw null;
 }
Example #6
0
 public static System.Runtime.CompilerServices.CallSiteBinder IsEvent(Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags flags, string name, System.Type context)
 {
     throw null;
 }
Example #7
0
 public static System.Runtime.CompilerServices.CallSiteBinder Convert(Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags flags, System.Type type, System.Type context)
 {
     throw null;
 }
 public static System.Runtime.CompilerServices.CallSiteBinder InvokeConstructor(Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags flags, System.Type?context, System.Collections.Generic.IEnumerable <Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo>?argumentInfo)
 {
     throw null;
 }
Example #9
0
 public static System.Runtime.CompilerServices.CallSiteBinder SetIndex(Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags flags, System.Type context, System.Collections.Generic.IEnumerable <Microsoft.CSharp.RuntimeBinder.CSharpArgumentInfo> argumentInfo)
 {
     return(default(System.Runtime.CompilerServices.CallSiteBinder));
 }
Example #10
0
 public static System.Runtime.CompilerServices.CallSiteBinder IsEvent(Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags flags, string name, System.Type context)
 {
     return(default(System.Runtime.CompilerServices.CallSiteBinder));
 }
Example #11
0
 public static System.Runtime.CompilerServices.CallSiteBinder Convert(Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags flags, System.Type type, System.Type context)
 {
     return(default(System.Runtime.CompilerServices.CallSiteBinder));
 }