aboutsummaryrefslogtreecommitdiffstatsci
path: root/src/CompilerServices
diff options
context:
space:
mode:
authorJean-Philippe Bruyère <jp_bruyere@hotmail.com>2018-12-10 18:48:30 +0100
committerJean-Philippe Bruyère <jp_bruyere@hotmail.com>2018-12-10 18:48:30 +0100
commit3c6887e62dcce8d3e1c9693eaf580932521b4014 (patch)
tree5cf08a7589dce289d8dca6d60e328b32935a63a5 /src/CompilerServices
parentfd3cf7597b2c3084c41993fe2043a484466c4fa9 (diff)
netcore support
Diffstat (limited to 'src/CompilerServices')
-rw-r--r--src/CompilerServices/CompilerServices.cs931
1 files changed, 0 insertions, 931 deletions
diff --git a/src/CompilerServices/CompilerServices.cs b/src/CompilerServices/CompilerServices.cs
deleted file mode 100644
index 5112fb12..00000000
--- a/src/CompilerServices/CompilerServices.cs
+++ /dev/null
@@ -1,931 +0,0 @@
-//
-// CompilerServices.cs
-//
-// Author:
-// Jean-Philippe Bruyère <jp.bruyere@hotmail.com>
-//
-// Copyright (c) 2013-2017 Jean-Philippe Bruyère
-//
-// Permission is hereby granted, free of charge, to any person obtaining a copy
-// of this software and associated documentation files (the "Software"), to deal
-// in the Software without restriction, including without limitation the rights
-// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-// copies of the Software, and to permit persons to whom the Software is
-// furnished to do so, subject to the following conditions:
-//
-// The above copyright notice and this permission notice shall be included in
-// all copies or substantial portions of the Software.
-//
-// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
-// THE SOFTWARE.
-
-using System;
-using System.Reflection.Emit;
-using System.Reflection;
-using System.Diagnostics;
-using System.Linq;
-using System.Collections.Generic;
-using System.Runtime.CompilerServices;
-using System.Xml;
-using Crow.IML;
-
-
-namespace Crow.IML
-{
- public static class CompilerServices
- {
- internal static Type TObject = typeof(object);
- internal static MethodInfo stringEquals = typeof (string).GetMethod("Equals", new Type [3] { typeof (string), typeof (string), typeof (StringComparison) });
- internal static MethodInfo miObjToString = typeof(object).GetMethod("ToString");
- internal static MethodInfo miGetType = typeof(object).GetMethod("GetType");
- internal static MethodInfo miParseEnum = typeof(Enum).GetMethod("Parse", BindingFlags.Static | BindingFlags.Public,
- Type.DefaultBinder, new Type [] {typeof (Type), typeof (string), typeof (bool)}, null);
-
- internal static MethodInfo miGetTypeFromHandle = typeof(Type).GetMethod("GetTypeFromHandle");
- internal static MethodInfo miGetEvent = typeof(Type).GetMethod("GetEvent", new Type[] {typeof(string)});
-
- internal static MethodInfo miMIInvoke = typeof(MethodInfo).GetMethod ("Invoke", new Type[] {
- typeof(object),
- typeof(object[])
- });
-
- internal static MethodInfo miCreateBoundDel = typeof(Delegate).GetMethod ("CreateDelegate", new Type[] { typeof(Type), typeof(object), typeof(MethodInfo) });//create bound delegate
- internal static MethodInfo miGetColCount = typeof(System.Collections.ICollection).GetProperty("Count").GetGetMethod();
- internal static MethodInfo miGetDelegateListItem = typeof(List<Delegate>).GetMethod("get_Item", new Type[] { typeof(Int32) });
-
- internal static MethodInfo miCompileDynEventHandler = typeof(CompilerServices).GetMethod ("compileDynEventHandler", BindingFlags.Static | BindingFlags.NonPublic);
- internal static MethodInfo miRemEvtHdlByName = typeof(CompilerServices).GetMethod("removeEventHandlerByName", BindingFlags.Static | BindingFlags.NonPublic);
- internal static MethodInfo miRemEvtHdlByTarget = typeof(CompilerServices).GetMethod("removeEventHandlerByTarget", BindingFlags.Static | BindingFlags.NonPublic);
- internal static MethodInfo miGetMethInfoWithRefx = typeof(CompilerServices).GetMethod ("getMethodInfoWithReflexion", BindingFlags.Static | BindingFlags.NonPublic);
- internal static MethodInfo miGetMembIinfoWithRefx = typeof(CompilerServices).GetMethod("getMemberInfoWithReflexion", BindingFlags.Static | BindingFlags.NonPublic);
- internal static MethodInfo miSetValWithRefx = typeof(CompilerServices).GetMethod("setValueWithReflexion", BindingFlags.Static | BindingFlags.NonPublic);
- internal static MethodInfo miGetValWithRefx = typeof(CompilerServices).GetMethod("getValueWithReflexion", BindingFlags.Static | BindingFlags.NonPublic);
- internal static MethodInfo miCreateDel = typeof(CompilerServices).GetMethod ("createDel", BindingFlags.Static | BindingFlags.NonPublic);
- internal static MethodInfo miGetImplOp = typeof(CompilerServices).GetMethod ("getImplicitOp", BindingFlags.Static | BindingFlags.NonPublic);
- internal static MethodInfo miGetDataTypeAndFetch = typeof(CompilerServices).GetMethod("getDataTypeAndFetch", BindingFlags.Static | BindingFlags.NonPublic);
-
-
- internal static MethodInfo miGoUpLevels = typeof(CompilerServices).GetMethod("goUpNbLevels", BindingFlags.Static | BindingFlags.NonPublic);
-
- internal static FieldInfo fiCachedDel = typeof(Instantiator).GetField("cachedDelegates", BindingFlags.Instance | BindingFlags.NonPublic);
- internal static FieldInfo fiTemplateBinding = typeof(Instantiator).GetField("templateBinding", BindingFlags.Instance | BindingFlags.NonPublic);
- internal static MethodInfo miDSChangeEmitHelper = typeof(Instantiator).GetMethod("dataSourceChangedEmitHelper", BindingFlags.Instance | BindingFlags.NonPublic);
- internal static MethodInfo miDSReverseBinding = typeof(Instantiator).GetMethod("dataSourceReverseBinding", BindingFlags.Static | BindingFlags.NonPublic);
-
- internal static FieldInfo miSetCurIface = typeof(GraphicObject).GetField ("IFace", BindingFlags.Public | BindingFlags.Instance);
- internal static MethodInfo miFindByName = typeof (GraphicObject).GetMethod ("FindByName");
- internal static MethodInfo miGetGObjItem = typeof(List<GraphicObject>).GetMethod("get_Item", new Type[] { typeof(Int32) });
- internal static MethodInfo miLoadDefaultVals = typeof (GraphicObject).GetMethod ("loadDefaultValues");
- internal static PropertyInfo piStyle = typeof (GraphicObject).GetProperty ("Style");
- internal static MethodInfo miGetLogicalParent = typeof(GraphicObject).GetProperty("LogicalParent").GetGetMethod();
- internal static MethodInfo miGetDataSource = typeof(GraphicObject).GetProperty("DataSource").GetGetMethod ();
- internal static EventInfo eiLogicalParentChanged = typeof(GraphicObject).GetEvent("LogicalParentChanged");
-
- internal static MethodInfo miIFaceLoad = typeof(Interface).GetMethod ("Load", BindingFlags.Instance | BindingFlags.Public);
- internal static MethodInfo miGetITemp = typeof(Interface).GetMethod ("GetItemTemplate", BindingFlags.Instance | BindingFlags.Public);
-
- internal static MethodInfo miAddITemp = typeof(Dictionary<string, ItemTemplate>).GetMethod ("set_Item", new Type[] { typeof(string), typeof(ItemTemplate) });
- internal static MethodInfo miGetITempFromDic = typeof(Dictionary<string, ItemTemplate>).GetMethod ("get_Item", new Type[] { typeof(string) });
- internal static FieldInfo fldItemTemplates = typeof(TemplatedGroup).GetField("ItemTemplates");
- internal static MethodInfo miLoadPage = typeof(TemplatedGroup).GetMethod ("loadPage", BindingFlags.Instance | BindingFlags.NonPublic| BindingFlags.Public);
- internal static MethodInfo miIsAlreadyExpanded = typeof(TemplatedGroup).GetMethod("emitHelperIsAlreadyExpanded", BindingFlags.Instance | BindingFlags.NonPublic);
-
- internal static MethodInfo miCreateExpDel = typeof(ItemTemplate).GetMethod ("CreateExpandDelegate");
- internal static FieldInfo fiFetchMethodName = typeof(ItemTemplate).GetField("fetchMethodName", BindingFlags.Instance | BindingFlags.NonPublic);
-
- #if DESIGN_MODE
- internal static MethodInfo miDicStrStrAdd = typeof(Dictionary<string, string>).GetMethod ("set_Item", new Type[] { typeof(string), typeof(string) });
- #endif
-
- #region tree handling methods
- internal static FieldInfo fiChild = typeof(PrivateContainer).GetField ("child", BindingFlags.Instance | BindingFlags.NonPublic);
- internal static MethodInfo miSetChild = typeof (Container).GetMethod ("SetChild");
- internal static MethodInfo miAddChild = typeof (Group).GetMethod ("AddChild");
- internal static FieldInfo fiChildren = typeof(Group).GetField ("children", BindingFlags.Instance | BindingFlags.NonPublic);
- internal static MethodInfo miLoadTmp = typeof (TemplatedControl).GetMethod ("loadTemplate", BindingFlags.Instance | BindingFlags.NonPublic);
- internal static PropertyInfo piContent = typeof(TemplatedContainer).GetProperty ("Content");
- internal static MethodInfo miAddItem = typeof (TemplatedGroup).GetMethod ("AddItem", BindingFlags.Instance | BindingFlags.Public);
- internal static MethodInfo miGetItems = typeof(TemplatedGroup).GetProperty ("Items").GetGetMethod ();
- #endregion
-
- #region ValueChange & DSChange Reflexion member info
- internal static EventInfo eiValueChange = typeof (IValueChange).GetEvent ("ValueChanged");
- internal static MethodInfo miInvokeValueChange = eiValueChange.EventHandlerType.GetMethod ("Invoke");
- internal static Type [] argsBoundValueChange = { typeof (object), typeof (object), miInvokeValueChange.GetParameters () [1].ParameterType };
- internal static Type [] argsValueChange = { typeof (object), miInvokeValueChange.GetParameters () [1].ParameterType };
- internal static FieldInfo fiVCNewValue = typeof (ValueChangeEventArgs).GetField ("NewValue");
- internal static FieldInfo fiVCMbName = typeof (ValueChangeEventArgs).GetField ("MemberName");
- internal static MethodInfo miValueChangeAdd = eiValueChange.GetAddMethod ();
-
- internal static EventInfo eiDSChange = typeof (GraphicObject).GetEvent ("DataSourceChanged");
- internal static MethodInfo miInvokeDSChange = eiDSChange.EventHandlerType.GetMethod ("Invoke");
- internal static Type [] argsBoundDSChange = {typeof (object), typeof (object), miInvokeDSChange.GetParameters () [1].ParameterType };
- internal static FieldInfo fiDSCNewDS = typeof (DataSourceChangeEventArgs).GetField ("NewDataSource");
- internal static FieldInfo fiDSCOldDS = typeof (DataSourceChangeEventArgs).GetField ("OldDataSource");
- internal static Type ehTypeDSChange = eiDSChange.EventHandlerType;
- #endregion
-
- /// <summary>
- /// Loc0 is the current graphic object and arg2 of loader is the current interface
- /// </summary>
- /// <param name="il">Il.</param>
- public static void emitSetCurInterface(ILGenerator il){
- il.Emit (OpCodes.Ldloc_0);
- il.Emit (OpCodes.Ldarg_1);
- il.Emit (OpCodes.Stfld, miSetCurIface);
- }
-
- 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) {
- //load type of enum
- il.Emit(OpCodes.Ldtoken, pi.PropertyType);
- il.Emit(OpCodes.Call, CompilerServices.miGetTypeFromHandle);
- //load enum value name
- il.Emit (OpCodes.Ldstr, Convert.ToString (val));//TODO:implement here string format?
- //load false
- il.Emit (OpCodes.Ldc_I4_0);
- il.Emit (OpCodes.Call, CompilerServices.miParseEnum);
-
- if (CompilerServices.miParseEnum.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.Call, miParse);
-
- if (miParse.ReturnType != pi.PropertyType)
- il.Emit (OpCodes.Unbox_Any, pi.PropertyType);
- }
- }
- il.Emit (OpCodes.Callvirt, pi.GetSetMethod ());
- }
-
- #region conversions
-
- internal static MethodInfo GetConvertMethod (Type targetType)
- {
- string name;
-
- if (targetType == typeof (bool))
- name = "ToBoolean";
- else if (targetType == typeof (byte))
- name = "ToByte";
- else if (targetType == typeof (short))
- name = "ToInt16";
- else if (targetType == typeof (int))
- name = "ToInt32";
- else if (targetType == typeof (long))
- name = "ToInt64";
- else if (targetType == typeof (double))
- name = "ToDouble";
- else if (targetType == typeof (float))
- name = "ToSingle";
- else if (targetType == typeof (string))
- return typeof (object).GetMethod ("ToString", Type.EmptyTypes);
- else //try to find implicit convertion
- throw new NotImplementedException (string.Format ("Conversion to {0} is not implemented.", targetType.Name));
-
- return typeof (Convert).GetMethod (name, BindingFlags.Static | BindingFlags.Public, null, new Type [] { typeof (object) }, null);
- }
- #endregion
-
- #region Reflexion helpers
- static MemberInfo getMemberInfoWithReflexion(object instance, string member){
- Type t = instance.GetType();
- MemberInfo mi = t.GetMember (member)?.FirstOrDefault();
- if (mi == null)
- mi = CompilerServices.SearchExtMethod (t, member);
- return mi;
- }
- static MethodInfo getMethodInfoWithReflexion(object instance, string method){
- return instance.GetType ().GetMethod (method, BindingFlags.Instance | BindingFlags.NonPublic | BindingFlags.Public);
- }
- /// <summary>
- /// set value, convert if required
- /// </summary>
- /// <param name="dest">Destination instance</param>
- /// <param name="value">Value</param>
- /// <param name="destMember">Destination member</param>
- static void setValueWithReflexion(object dest, object value, string destMember){
- Type destType = null;
- Type origType = null;
- object convertedVal = null;
-
- MemberInfo miDest = getMemberInfoWithReflexion (dest, destMember);
-
- if (miDest == null) {
- Debug.WriteLine ("Reverse template binding error: " + destMember + " not found in " + dest);
- return;
- }
-
- if (miDest.MemberType == MemberTypes.Property)
- destType =(miDest as PropertyInfo).PropertyType;
- else if (miDest.MemberType == MemberTypes.Field)
- destType =(miDest as FieldInfo).FieldType;
-
- try {
- if (value != null) {
- if (destType == TObject)//TODO: check that test of destType is not causing problems
- convertedVal = value;
- else {
- origType = value.GetType ();
- if (destType.IsAssignableFrom (origType))
- convertedVal = Convert.ChangeType (value, destType);
- else if (origType == typeof(string) & destType.IsPrimitive)
- convertedVal = Convert.ChangeType(value, destType);
- else if (origType.IsPrimitive & destType.IsPrimitive)
- convertedVal = GetConvertMethod (destType).Invoke (null, new Object[] { value });
- else
- convertedVal = getImplicitOp (origType, destType).Invoke (value, null);
- }
- }
- } catch (Exception ex) {
- Debug.WriteLine (ex.ToString ());
- return;
- }
-
- if (miDest.MemberType == MemberTypes.Property)
- (miDest as PropertyInfo).SetValue (dest, convertedVal);
- else if (miDest.MemberType == MemberTypes.Field)
- (miDest as FieldInfo).SetValue (dest, convertedVal);
- }
- /// <summary>
- /// Gets value with reflexion, return empty string ("") for string and object and return
- /// default value for valueType data.
- /// </summary>
- static object getValueWithReflexion(object instance, MemberInfo mi){
- object tmp = null;
- Type dstType = null;
- if (mi == null)
- return null;
- try {
- if (mi.MemberType == MemberTypes.Property) {
- PropertyInfo pi = mi as PropertyInfo;
- tmp = pi.GetValue (instance);
- dstType = pi.PropertyType;
- }else if (mi.MemberType == MemberTypes.Field) {
- FieldInfo fi = mi as FieldInfo;
- tmp = fi.GetValue (instance);
- dstType = fi.FieldType;
- }else if (mi.MemberType == MemberTypes.Method) {
- MethodInfo gi = mi as MethodInfo;
- if (gi.IsStatic)
- tmp = gi.Invoke(null, new object[] {instance});
- else
- tmp = gi.Invoke(instance, null);
- dstType = gi.ReturnType;
- }
-
-
- if (tmp != null)
- return tmp;
- if (dstType == typeof(string) || dstType == CompilerServices.TObject)//TODO:object should be allowed to return null and not ""
- return "";
- if (dstType.IsValueType)
- return Activator.CreateInstance (dstType);
- } catch (Exception ex) {
- Debug.WriteLine (ex.ToString ());
- return "";
- }
-
- return null;
- }
- /// <summary>
- /// Gets all extension methods defined in assembly for Type
- /// </summary>
- /// <returns>Extension methods enumerable</returns>
- /// <param name="assembly">Assembly</param>
- /// <param name="extendedType">Extended type to search for</param>
- internal static IEnumerable<MethodInfo> GetExtensionMethods (Assembly assembly,
- Type extendedType)
- {
- IEnumerable<MethodInfo> query = null;
- Type curType = extendedType;
-
- do {
- query = from type in assembly.GetTypes ()
- where type.IsSealed && !type.IsGenericType && !type.IsNested
- from method in type.GetMethods (BindingFlags.Static
- | BindingFlags.Public | BindingFlags.NonPublic)
- where method.IsDefined (typeof (ExtensionAttribute), false)
- where method.GetParameters () [0].ParameterType == curType
- select method;
-
- if (query.Count () > 0)
- break;
-
- curType = curType.BaseType;
- } while (curType != null);
-
- return query;
- }
- /// <summary>
- /// search for extentions method in entry assembly then in crow assembly
- /// </summary>
- /// <returns>Extention MethodInfo</returns>
- /// <param name="t">Extended type</param>
- /// <param name="methodName">Extention method name</param>
- internal static MethodInfo SearchExtMethod(Type t, string methodName){
- MethodInfo mi = null;
- mi = GetExtensionMethods (Assembly.GetEntryAssembly(), t)
- .Where (em => em.Name == methodName).FirstOrDefault ();
- if (mi != null)
- return mi;
-
- return GetExtensionMethods (Assembly.GetExecutingAssembly(), t)
- .Where (em => em.Name == methodName).FirstOrDefault ();
- }
- /// <summary>
- /// retrieve event handler in class or ancestors
- /// </summary>
- static FieldInfo getEventHandlerField (Type type, string eventName)
- {
- FieldInfo fi;
- Type ty = type;
- do {
- fi = ty.GetField (eventName,
- BindingFlags.NonPublic |
- BindingFlags.Instance |
- BindingFlags.GetField);
- ty = ty.BaseType;
- if (ty == null)
- break;
- } while (fi == null);
- return fi;
- }
- /// <summary>
- /// search for an implicit conversion method in origine or destination classes
- /// </summary>
- static MethodInfo getImplicitOp(Type origType, Type dstType){
- foreach(MethodInfo mi in origType.GetMethods(BindingFlags.Public|BindingFlags.Static)){
- if (mi.Name == "op_Implicit") {
- if (mi.ReturnType == dstType && mi.GetParameters ().FirstOrDefault ().ParameterType == origType)
- return mi;
- }
- }
- foreach(MethodInfo mi in dstType.GetMethods(BindingFlags.Public|BindingFlags.Static)){
- if (mi.Name == "op_Implicit") {
- if (mi.ReturnType == dstType && mi.GetParameters ().FirstOrDefault ().ParameterType == origType)
- return mi;
- }
- }
- return null;
- }
- #endregion
-
- /// <summary>
- /// Emits tree parsing command to fetch dest instance starting from orig node
- /// </summary>
- internal static void emitGetInstance (ILGenerator il, NodeAddress orig, NodeAddress dest){
- int ptr = 0;
- while (orig [ptr] == dest [ptr]) {
- ptr++;
- if (ptr == orig.Count || ptr == dest.Count)
- break;
- }
- for (int i = 0; i < orig.Count - ptr; i++)
- il.Emit (OpCodes.Callvirt, CompilerServices.miGetLogicalParent);
- while (ptr < dest.Count) {
- emitGetChild (il, dest [ptr-1].CrowType, dest [ptr].Index);
- ptr++;
- }
- }
- /// <summary>
- /// Emits tree parsing commands to get child starting at root node
- /// </summary>
- /// <param name="il">MSIL generator</param>
- /// <param name="dest">Absolute Node Address of the instance to get</param>
- internal static void emitGetInstance (ILGenerator il, NodeAddress dest){
- if (dest == null)
- return;
- for (int i = 0; i < dest.Count - 1; i++)
- emitGetChild (il, dest [i].CrowType, dest [i + 1].Index);
- }
- /// <summary>
- /// Emits msil to fetch chil instance of current GraphicObject on the stack
- /// </summary>
- /// <param name="il">Il generator</param>
- /// <param name="parentType">Parent type</param>
- /// <param name="index">Index of child, -1 for template root</param>
- internal static void emitGetChild(ILGenerator il, Type parentType, int index){
- if (typeof (Group).IsAssignableFrom (parentType)) {
- il.Emit (OpCodes.Ldfld, fiChildren);
- il.Emit(OpCodes.Ldc_I4, index);
- il.Emit (OpCodes.Callvirt, miGetGObjItem);
- return;
- }
- if (typeof(Container).IsAssignableFrom (parentType) || index < 0) {
- il.Emit (OpCodes.Ldfld, fiChild);
- return;
- }
- if (typeof(TemplatedContainer).IsAssignableFrom (parentType)) {
- il.Emit (OpCodes.Callvirt, piContent.GetGetMethod());
- return;
- }
- if (typeof(TemplatedGroup).IsAssignableFrom (parentType)) {
- il.Emit (OpCodes.Callvirt, miGetItems);
- il.Emit(OpCodes.Ldc_I4, index);
- il.Emit (OpCodes.Callvirt, miGetGObjItem);
- return;
- }
- }
-
- /// <summary>
- /// Emit MSIL for conversion from orig type to dest type
- /// </summary>
- internal static void emitConvert(ILGenerator il, Type origType, Type destType){
- if (destType == CompilerServices.TObject)
- return;
- if (destType == typeof(string)) {
- System.Reflection.Emit.Label emitNullStr = il.DefineLabel ();
- System.Reflection.Emit.Label endConvert = il.DefineLabel ();
- il.Emit (OpCodes.Dup);
- il.Emit (OpCodes.Brfalse, emitNullStr);
- il.Emit (OpCodes.Callvirt, CompilerServices.miObjToString);
- il.Emit (OpCodes.Br, endConvert);
- il.MarkLabel (emitNullStr);
- il.Emit (OpCodes.Pop);//remove null string from stack
- il.Emit (OpCodes.Ldstr, "");//replace with empty string
- il.MarkLabel (endConvert);
- }else if (origType.IsValueType) {
- if (destType != origType) {
- MethodInfo miIO = getImplicitOp (origType, destType);
- if (miIO != null)
- {
- System.Reflection.Emit.Label emitCreateDefault = il.DefineLabel();
- System.Reflection.Emit.Label emitContinue = il.DefineLabel();
- LocalBuilder lbStruct = il.DeclareLocal(origType);
- il.Emit(OpCodes.Dup);
- il.Emit(OpCodes.Brfalse, emitCreateDefault);
- il.Emit(OpCodes.Unbox_Any, origType);
- il.Emit(OpCodes.Br, emitContinue);
- il.MarkLabel(emitCreateDefault);
- il.Emit(OpCodes.Pop);//pop null value
- il.Emit(OpCodes.Ldloca, lbStruct);
- il.Emit(OpCodes.Initobj, origType);
- il.Emit(OpCodes.Ldloc, lbStruct);
- il.MarkLabel(emitContinue);
- il.Emit(OpCodes.Call, miIO);
- }
- else
- {
- MethodInfo miconv = CompilerServices.GetConvertMethod(destType);
- if (miconv.IsStatic)
- il.Emit(OpCodes.Call, miconv);
- else
- il.Emit(OpCodes.Callvirt, miconv);
- }
- }else
- il.Emit (OpCodes.Unbox_Any, destType);//TODO:double check this
- } else {
- if (destType.IsAssignableFrom(origType))
- il.Emit (OpCodes.Castclass, destType);
- else {
- //implicit conversion can't be defined from or to object base class,
- //so we will check if object underlying type is one of the implicit converter of destType
- if (origType == TObject) {//test all implicit converter to destType on obj
- System.Reflection.Emit.Label emitTestNextImpOp;
- System.Reflection.Emit.Label emitImpOpFound = il.DefineLabel ();
- foreach (MethodInfo mi in destType.GetMethods(BindingFlags.Public|BindingFlags.Static)) {
- if (mi.Name == "op_Implicit") {
- if (mi.GetParameters () [0].ParameterType == destType)
- continue;
- emitTestNextImpOp = il.DefineLabel ();
- il.Emit (OpCodes.Dup);
- il.Emit (OpCodes.Isinst, mi.GetParameters () [0].ParameterType);
- il.Emit (OpCodes.Brfalse, emitTestNextImpOp);
- if (mi.GetParameters () [0].ParameterType.IsValueType)
- il.Emit (OpCodes.Unbox_Any, mi.GetParameters () [0].ParameterType);
- else
- il.Emit (OpCodes.Isinst, mi.GetParameters () [0].ParameterType);
-
- il.Emit (OpCodes.Call, mi);
- il.Emit (OpCodes.Br, emitImpOpFound);
-
- il.MarkLabel (emitTestNextImpOp);
- }
- }
- //il.Emit (OpCodes.Br, emitImpOpNotFound);
- il.MarkLabel (emitImpOpFound);
- } else {//search both orig and dest types for implicit operators
- MethodInfo miIO = getImplicitOp (origType, destType);
- if (miIO != null)
- il.Emit (OpCodes.Call, miIO);
- }
- }
- }
- }
- /// <summary>
- /// check type of current object on the stack and convert to dest type,
- /// use loc_0 so store it as object!!!
- /// </summary>
- internal static void emitConvert(ILGenerator il, Type dstType){
- System.Reflection.Emit.Label endConvert = il.DefineLabel ();
- System.Reflection.Emit.Label convert = il.DefineLabel ();
-
- il.Emit (OpCodes.Dup);
- il.Emit (OpCodes.Isinst, dstType);
- il.Emit (OpCodes.Brfalse, convert);
-
- if (dstType.IsValueType)
- il.Emit (OpCodes.Unbox_Any, dstType);
- else
- il.Emit (OpCodes.Isinst, dstType);
- il.Emit (OpCodes.Br, endConvert);
-
- il.MarkLabel (convert);
-
- if (dstType == typeof(string)) {
- System.Reflection.Emit.Label emitNullStr = il.DefineLabel ();
- il.Emit (OpCodes.Dup);
- il.Emit (OpCodes.Brfalse, emitNullStr);
- il.Emit (OpCodes.Callvirt, CompilerServices.miObjToString);
- il.Emit (OpCodes.Br, endConvert);
- il.MarkLabel (emitNullStr);
- il.Emit (OpCodes.Pop);//remove null string from stack
- il.Emit (OpCodes.Ldstr, "");//replace with empty string
- } else if (dstType.IsPrimitive) {
- //il.Emit (OpCodes.Unbox_Any, dstType);
- MethodInfo miconv = CompilerServices.GetConvertMethod(dstType);
- if (miconv.IsStatic)
- il.Emit(OpCodes.Call, miconv);
- else
- il.Emit(OpCodes.Callvirt, miconv);
- } else if (dstType.IsValueType) {
- il.Emit (OpCodes.Unbox_Any, dstType);
- } else{
- il.Emit (OpCodes.Stloc_0); //save orig value in loc0
- //first check if not null
- il.Emit (OpCodes.Ldloc_0);
- il.Emit (OpCodes.Dup);
- il.Emit (OpCodes.Brfalse, endConvert);
- il.Emit (OpCodes.Callvirt, miGetType);
- il.Emit (OpCodes.Ldtoken, dstType);//push destination property type for testing
- il.Emit (OpCodes.Call, CompilerServices.miGetTypeFromHandle);
- il.Emit (OpCodes.Call, miGetImplOp);
- il.Emit (OpCodes.Dup);
- convert = il.DefineLabel ();
- il.Emit (OpCodes.Brtrue, convert);
- il.Emit (OpCodes.Pop);
- il.Emit (OpCodes.Ldloc_0);
- il.Emit (OpCodes.Isinst, dstType);
- il.Emit (OpCodes.Br, endConvert);
-
- il.MarkLabel (convert);
- il.Emit (OpCodes.Ldnull);//null instance for invoke
- il.Emit (OpCodes.Ldc_I4_1);
- il.Emit(OpCodes.Newarr, CompilerServices.TObject);
- il.Emit (OpCodes.Dup);//duplicate the array ref
- il.Emit (OpCodes.Ldc_I4_0);//push the index 0
- il.Emit (OpCodes.Ldloc_0);//push the orig value to convert
- il.Emit (OpCodes.Stelem, CompilerServices.TObject);//set the array element at index 0
- il.Emit (OpCodes.Callvirt, miMIInvoke);
- }
-
- il.MarkLabel (endConvert);
- }
-
- /// <summary>
- /// Removes delegate from event handler by name
- /// </summary>
- static void removeEventHandlerByName(object instance, string eventName, string delegateName){
- Type t = instance.GetType ();
- FieldInfo fiEvt = getEventHandlerField (t, eventName);
- if (fiEvt == null) {
- #if DEBUG_BINDING
- Debug.WriteLine ("RemoveHandlerByName: Event '" + eventName + "' not found in " + instance);
- #endif
- return;
- }
- EventInfo eiEvt = t.GetEvent (eventName);
- MulticastDelegate multiDel = fiEvt.GetValue (instance) as MulticastDelegate;
- if (multiDel != null) {
- foreach (Delegate d in multiDel.GetInvocationList()) {
- if (d.Method.Name == delegateName) {
- eiEvt.RemoveEventHandler (instance, d);
- #if DEBUG_BINDING
- Debug.WriteLine ("\t{0} handler removed in {1} for: {2}", d.Method.Name,instance, eventName);
- #endif
- }
- }
- }
- }
- /// <summary>
- /// Removes delegate from event handler by searching for the object they are bond to
- /// </summary>
- static void removeEventHandlerByTarget(object instance, string eventName, object target){
- Type t = instance.GetType ();
- FieldInfo fiEvt = getEventHandlerField (t, eventName);
- EventInfo eiEvt = t.GetEvent (eventName);
- MulticastDelegate multiDel = fiEvt.GetValue (instance) as MulticastDelegate;
- if (multiDel != null) {
- foreach (Delegate d in multiDel.GetInvocationList()) {
- if (d.Target == target) {
- eiEvt.RemoveEventHandler (instance, d);
- #if DEBUG_BINDING
- Debug.WriteLine ("\t{0} handler removed in {1} for: {2}", d.Method.Name,instance, eventName);
- #endif
- }
- }
- }
- }
- /// <summary>
- /// create delegate helper
- /// </summary>
- static Delegate createDel(object instance, Type eventType, string method){
- Type t = instance.GetType ();
- MethodInfo mi = t.GetMethod (method, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
- if (mi == null) {
- Debug.WriteLine ("Handler Method '{0}' not found in '{1}'", method, t);
- return null;
- }
- return Delegate.CreateDelegate (eventType, instance, mi);
- }
-
- internal static Delegate compileDynEventHandler(EventInfo sourceEvent, string expression, NodeAddress currentNode = null){
- #if DEBUG_BINDING
- Debug.WriteLine ("\tCompile Event {0}: {1}", sourceEvent.Name, expression);
- #endif
-
- Type lopType = null;
-
- if (currentNode == null)
- lopType = sourceEvent.DeclaringType;
- else
- lopType = currentNode.NodeType;
-
- #region Retrieve EventHandler parameter type
- MethodInfo evtInvoke = sourceEvent.EventHandlerType.GetMethod ("Invoke");
- ParameterInfo [] evtParams = evtInvoke.GetParameters ();
- Type handlerArgsType = evtParams [1].ParameterType;
- #endregion
-
- Type [] args = { CompilerServices.TObject, handlerArgsType };
- DynamicMethod dm = new DynamicMethod ("dyn_eventHandler",
- typeof(void),
- args, true);
- ILGenerator il = dm.GetILGenerator (256);
- il.Emit (OpCodes.Nop);
-
- string [] srcLines = expression.Trim ().Split (new char [] { ';' });
-
- foreach (string srcLine in srcLines) {
- if (string.IsNullOrEmpty (srcLine))
- continue;
- string [] operandes = srcLine.Trim ().Split (new char [] { '=' });
- if (operandes.Length != 2) //not an affectation
- throw new NotSupportedException ();
-
- System.Reflection.Emit.Label cancel = il.DefineLabel ();
- System.Reflection.Emit.Label cancelFinalSet = il.DefineLabel ();
- System.Reflection.Emit.Label success = il.DefineLabel ();
-
- BindingMember lop = new BindingMember (operandes [0].Trim ());
- BindingMember rop = new BindingMember (operandes [1].Trim ());
-
- il.Emit (OpCodes.Ldarg_0); //load sender ref onto the stack, the current node
-
- #region Left operande
- PropertyInfo lopPI = null;
-
- //in dyn handler, no datasource binding, so single name in expression are also handled as current node property
- if (lop.IsSingleName)
- lopPI = lopType.GetProperty (lop.Tokens [0]);
- else if (lop.IsCurrentNodeProperty)
- lopPI = lopType.GetProperty (lop.Tokens [1]);
- else
- lop.emitGetTarget (il, cancel);
- #endregion
-
- #region RIGHT OPERANDES
- if (rop.IsStringConstant){
- il.Emit (OpCodes.Ldstr, rop.Tokens[0]);
- lop.emitSetProperty (il);
- }else if (rop.IsSingleName && rop.Tokens[0] == "this"){
- il.Emit (OpCodes.Ldarg_0); //load sender ref onto the stack, the current node
- lop.emitSetProperty (il);
- }else if (rop.LevelsUp ==0 && !string.IsNullOrEmpty(rop.Tokens[0])) {//parsable constant depending on lop type
- //if left operand is member of current node, it's easy to fetch type, else we should use reflexion in msil
- if (lopPI == null){//accept GraphicObj members, but it's restricive
- //TODO: we should get the parse method by reflexion, or something else
- lopPI = typeof(GraphicObject).GetProperty (lop.Tokens [lop.Tokens.Length-1]);
- if (lopPI == null)
- throw new NotSupportedException ();
- }
-
- MethodInfo lopParseMi = CompilerServices.miParseEnum;
- if (lopPI.PropertyType.IsEnum){
- //load type of enum
- il.Emit(OpCodes.Ldtoken, lopPI.PropertyType);
- il.Emit(OpCodes.Call, CompilerServices.miGetTypeFromHandle);
- //load enum value name
- il.Emit (OpCodes.Ldstr, operandes [1].Trim ());
- //load false
- il.Emit (OpCodes.Ldc_I4_0);
- }else{
- lopParseMi = lopPI.PropertyType.GetMethod ("Parse");
- if (lopParseMi == null)
- throw new Exception (string.Format
- ("IML: no static 'Parse' method found in: {0}", lopPI.PropertyType.Name));
-
- il.Emit (OpCodes.Ldstr, operandes [1].Trim ());
- }
- if (lopParseMi.IsStatic)
- il.Emit (OpCodes.Call, lopParseMi);
- else
- il.Emit(OpCodes.Callvirt, lopParseMi);
- //il.Emit (OpCodes.Unbox_Any, lopPI.PropertyType);
- //emit left operand assignment
- il.Emit (OpCodes.Callvirt, lopPI.GetSetMethod());
- } else {//tree parsing and propert gets
- il.Emit (OpCodes.Ldarg_0); //load sender ref onto the stack, the current node
-
- rop.emitGetTarget (il, cancelFinalSet);
- rop.emitGetProperty (il, cancelFinalSet);
- lop.emitSetProperty (il);
- }
- #endregion
-
- il.Emit (OpCodes.Br, success);
-
- il.MarkLabel (cancelFinalSet);
- il.Emit (OpCodes.Pop); //pop null MemberInfo on the stack causing cancelation
- il.MarkLabel (cancel);
- il.Emit (OpCodes.Pop); //pop null instance on the stack causing cancelation
- il.MarkLabel (success);
- }
-
- il.Emit (OpCodes.Ret);
-
- return dm.CreateDelegate (sourceEvent.EventHandlerType);
- }
-
- /// <summary>
- /// MSIL helper, go n levels up
- /// </summary>
- /// <returns><c>true</c>, if logical parents are not null</returns>
- /// <param name="instance">Start Instance</param>
- /// <param name="levelCount">Levels to go upward</param>
- internal static ILayoutable goUpNbLevels(ILayoutable instance, int levelCount){
- ILayoutable tmp = instance;
- int i = 0;
- while (tmp != null && i < levelCount) {
- tmp = tmp.LogicalParent;
- i++;
- }
- return tmp;
- }
- /// <summary>
- /// Splits expression on semicolon but ignore those between accolades
- /// </summary>
- internal static string[] splitOnSemiColumnOutsideAccolades (string expression){
- List<String> exps = new List<string>();
- int accCount = 0;
- int expPtr = 0;
- for (int c = 0; c < expression.Length; c++) {
- switch (expression[c]){
- case '{':
- accCount++;
- break;
- case '}':
- accCount--;
- break;
- case ';':
- if (accCount > 0)
- break;
- exps.Add(expression.Substring(expPtr, c - expPtr - 1));
- expPtr = c + 1;
- break;
- }
- }
- if (exps.Count == 0)
- exps.Add(expression);
- return exps.ToArray ();
- }
- /// <summary>
- /// Try to get the type named strDataType, search first in crow assembly then in
- /// entry assembly.
- /// </summary>
- /// <returns>the corresponding type object if found</returns>
- /// <param name="strDataType">type name</param>
- internal static Type tryGetType (string strDataType){
- Type dataType = Type.GetType(strDataType);
- if (dataType != null)
- return dataType;
- Assembly a = Assembly.GetEntryAssembly ();
- foreach (Type expT in a.GetExportedTypes ()) {
- if (expT.Name == strDataType)
- return dataType;
- }
- return null;
- }
-
- internal static object getDataTypeAndFetch (object data, string fetchMethod){
- Type dataType = data.GetType();
- MethodInfo miGetDatas = dataType.GetMethod (fetchMethod, new Type[] {});
- if (miGetDatas == null)
- miGetDatas = CompilerServices.SearchExtMethod (dataType, fetchMethod);
-
- if (miGetDatas == null) {//in last resort, search among properties
- PropertyInfo piDatas = dataType.GetProperty (fetchMethod);
- if (piDatas == null) {
- FieldInfo fiDatas = dataType.GetField (fetchMethod);
- if (fiDatas == null)//and among fields
- throw new Exception ("Fetch data member not found in ItemTemplate: " + fetchMethod);
- return fiDatas.GetValue (data);
- }
- miGetDatas = piDatas.GetGetMethod ();
- if (miGetDatas == null)
- throw new Exception ("Read only property for fetching data in ItemTemplate: " + fetchMethod);
- }
- object tmp = miGetDatas.Invoke (data, null);
- return tmp;
- }
- }
-}
-