diff options
| author | j-p <jp.bruyere@live.be> | 2016-08-11 04:20:36 +0200 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2016-08-11 04:20:36 +0200 |
| commit | 81eb8c7a75ffbe8b6740b2a84a9ebff75da9b393 (patch) | |
| tree | 3225277358a2bba61c4496923ba39353c942098b /src/CompilerServices | |
| parent | 4d4a9116ea5c68b27f0b7c43db9682ab57738ae7 (diff) | |
| parent | 7560c0bb4a769210e289e2633ddf13d2617f8e6e (diff) | |
Merge pull request #18 from jpbruyere/BindingImprovement
Instantiator
Diffstat (limited to 'src/CompilerServices')
| -rw-r--r-- | src/CompilerServices/Bindings.cs | 27 | ||||
| -rw-r--r-- | src/CompilerServices/CompilerServices.cs | 124 |
2 files changed, 144 insertions, 7 deletions
diff --git a/src/CompilerServices/Bindings.cs b/src/CompilerServices/Bindings.cs index 8ece856c..64f412f6 100644 --- a/src/CompilerServices/Bindings.cs +++ b/src/CompilerServices/Bindings.cs @@ -41,6 +41,11 @@ namespace Crow public string DynMethodId { get { return dynMethodId; } } + public Type SourceType { + get { return Source == null ? null + : Source.Instance == null ? null + : Source.Instance.GetType();} + } public bool Resolved { get { return resolved; } @@ -123,10 +128,12 @@ namespace Crow //datasource binding object dataSource = (Source.Instance as GraphicObject).DataSource; if (dataSource == null) { + #if DEBUG_BINDING Debug.WriteLine ("\tDataSource is null => " + this.ToString()); + #endif return false; } - + Target = new MemberReference (dataSource); memberName = bindingExp [0]; } else { @@ -148,7 +155,7 @@ namespace Crow while (ptr < bindingExp.Length - 1) { if (tmpTarget == null) { #if DEBUG_BINDING - Debug.WriteLine ("\tERROR: target not found => " + this.ToString()); + Debug.WriteLine ("\tTarget not found => " + this.ToString()); #endif return false; } @@ -164,14 +171,12 @@ namespace Crow } if (tmpTarget == null) { -#if DEBUG_BINDING - Debug.WriteLine ("\tERROR: Binding Target not found => " + this.ToString()); -#endif + #if DEBUG_BINDING + Debug.WriteLine ("\tBinding Target not found => " + this.ToString()); + #endif return false; } - Target = new MemberReference (tmpTarget); - string [] bindTrg = bindingExp [ptr].Split ('.'); if (bindTrg.Length == 1) @@ -182,6 +187,14 @@ namespace Crow } else throw new Exception ("Syntax error in binding, expected 'go dot member'"); + if (tmpTarget == null) { + #if DEBUG_BINDING + Debug.WriteLine ("\tBinding Target not found => " + this.ToString()); + #endif + return false; + } + + Target = new MemberReference (tmpTarget); } if (Target.TryFindMember (memberName)) { diff --git a/src/CompilerServices/CompilerServices.cs b/src/CompilerServices/CompilerServices.cs index 0b69f970..d06cd29b 100644 --- a/src/CompilerServices/CompilerServices.cs +++ b/src/CompilerServices/CompilerServices.cs @@ -5,12 +5,136 @@ using System.Diagnostics; using System.Linq; using System.Collections.Generic; using System.Runtime.CompilerServices; +using System.Xml; namespace Crow { public static class CompilerServices { + static MethodInfo miAddBinding = typeof(GraphicObject).GetMethod ("BindMember"); + + + public static void emitBindingCreation(ILGenerator il, string memberName, string expression){ + il.Emit (OpCodes.Ldloc_0); + il.Emit (OpCodes.Ldstr, memberName); + il.Emit (OpCodes.Ldstr, expression); + il.Emit (OpCodes.Callvirt, miAddBinding); + } + + public static void EmitSetValue(ILGenerator il, PropertyInfo pi, object val){ + il.Emit (OpCodes.Ldloc_0); + + if (val == null) { + il.Emit (OpCodes.Ldnull); + il.Emit (OpCodes.Callvirt, pi.GetSetMethod ()); + return; + } + Type dvType = val.GetType (); + + if (dvType.IsValueType) { + if (pi.PropertyType.IsValueType) { + if (pi.PropertyType.IsEnum) { + if (pi.PropertyType != dvType) + throw new Exception ("Enum mismatch in default values: " + pi.PropertyType.FullName); + il.Emit (OpCodes.Ldc_I4, Convert.ToInt32 (val)); + } else { + switch (Type.GetTypeCode (dvType)) { + case TypeCode.Boolean: + if ((bool)val == true) + il.Emit (OpCodes.Ldc_I4_1); + else + il.Emit (OpCodes.Ldc_I4_0); + break; + // case TypeCode.Empty: + // break; + // case TypeCode.Object: + // break; + // case TypeCode.DBNull: + // break; + // case TypeCode.SByte: + // break; + // case TypeCode.Decimal: + // break; + // case TypeCode.DateTime: + // break; + case TypeCode.Char: + il.Emit (OpCodes.Ldc_I4, Convert.ToChar (val)); + break; + case TypeCode.Byte: + case TypeCode.Int16: + case TypeCode.Int32: + il.Emit (OpCodes.Ldc_I4, Convert.ToInt32 (val)); + break; + case TypeCode.UInt16: + case TypeCode.UInt32: + il.Emit (OpCodes.Ldc_I4, Convert.ToUInt32 (val)); + break; + case TypeCode.Int64: + il.Emit (OpCodes.Ldc_I8, Convert.ToInt64 (val)); + break; + case TypeCode.UInt64: + il.Emit (OpCodes.Ldc_I8, Convert.ToUInt64 (val)); + break; + case TypeCode.Single: + il.Emit (OpCodes.Ldc_R4, Convert.ToSingle (val)); + break; + case TypeCode.Double: + il.Emit (OpCodes.Ldc_R8, Convert.ToDouble (val)); + break; + case TypeCode.String: + il.Emit (OpCodes.Ldstr, Convert.ToString (val)); + break; + default: + il.Emit (OpCodes.Pop); + return; + } + } + } else + throw new Exception ("Expecting valuetype in default values for: " + pi.Name); + }else{ + //surely a class or struct + if (dvType != typeof(string)) + throw new Exception ("Expecting String in default values for: " + pi.Name); + if (pi.PropertyType == typeof(string)) + il.Emit (OpCodes.Ldstr, Convert.ToString (val)); + else if (pi.PropertyType.IsEnum) { + MethodInfo miParse = typeof(Enum).GetMethod + ("Parse", BindingFlags.Static | BindingFlags.Public, + Type.DefaultBinder, new Type [] {typeof (Type), typeof (string), typeof (bool)}, null); + + if (miParse == null) + throw new Exception ("Enum Parse method not found"); + + //load type of enum + il.Emit(OpCodes.Ldtoken, pi.PropertyType); + il.Emit(OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle", new + Type[1]{typeof(RuntimeTypeHandle)})); + //load enum value name + il.Emit (OpCodes.Ldstr, Convert.ToString (val));//TODO:is this convert required? + //load false + il.Emit (OpCodes.Ldc_I4_0); + il.Emit (OpCodes.Callvirt, miParse); + + if (miParse.ReturnType != pi.PropertyType) + il.Emit (OpCodes.Unbox_Any, pi.PropertyType); + } else { + MethodInfo miParse = pi.PropertyType.GetMethod + ("Parse", BindingFlags.Static | BindingFlags.Public, + Type.DefaultBinder, new Type [] {typeof (string)},null); + if (miParse == null) + throw new Exception ("no Parse method found for: " + pi.PropertyType.FullName); + + il.Emit (OpCodes.Ldstr, Convert.ToString (val));//TODO:is this convert required? + il.Emit (OpCodes.Callvirt, miParse); + + if (miParse.ReturnType != pi.PropertyType) + il.Emit (OpCodes.Unbox_Any, pi.PropertyType); + } + } + il.Emit (OpCodes.Callvirt, pi.GetSetMethod ()); + } + public static void ResolveBindings (List<Binding> Bindings) { if (Bindings == null) |