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)); }
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)); }
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; }
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; }
public static System.Runtime.CompilerServices.CallSiteBinder IsEvent(Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags flags, string name, System.Type context) { throw null; }
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; }
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)); }
public static System.Runtime.CompilerServices.CallSiteBinder IsEvent(Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags flags, string name, System.Type context) { return(default(System.Runtime.CompilerServices.CallSiteBinder)); }
public static System.Runtime.CompilerServices.CallSiteBinder Convert(Microsoft.CSharp.RuntimeBinder.CSharpBinderFlags flags, System.Type type, System.Type context) { return(default(System.Runtime.CompilerServices.CallSiteBinder)); }