/// <summary> Loads the default values from XML attributes default </summary> public void loadDefaultValues() { #if DEBUG_LOAD Debug.WriteLine ("LoadDefValues for " + this.ToString ()); #endif Type thisType = this.GetType (); if (!string.IsNullOrEmpty (Style)) { if (Interface.DefaultValuesLoader.ContainsKey (Style)) { Interface.DefaultValuesLoader [Style] (this); return; } } else { if (Interface.DefaultValuesLoader.ContainsKey (thisType.FullName)) { Interface.DefaultValuesLoader [thisType.FullName] (this); return; } else if (!Interface.Styling.ContainsKey (thisType.FullName)) { if (Interface.DefaultValuesLoader.ContainsKey (thisType.Name)) { Interface.DefaultValuesLoader [thisType.Name] (this); return; } } } List<Style> styling = new List<Style>(); //Search for a style matching : //1: Full class name, with full namespace //2: class name //3: style may have been registered with their ressource ID minus .style extention // those files being placed in a Styles folder string styleKey = Style; if (!string.IsNullOrEmpty (Style)) { if (Interface.Styling.ContainsKey (Style)) { styling.Add (Interface.Styling [Style]); } } if (Interface.Styling.ContainsKey (thisType.FullName)) { styling.Add (Interface.Styling [thisType.FullName]); if (string.IsNullOrEmpty (styleKey)) styleKey = thisType.FullName; } if (Interface.Styling.ContainsKey (thisType.Name)) { styling.Add (Interface.Styling [thisType.Name]); if (string.IsNullOrEmpty (styleKey)) styleKey = thisType.Name; } if (string.IsNullOrEmpty (styleKey)) styleKey = thisType.FullName; //Reflexion being very slow compared to dyn method or delegates, //I compile the initial values coded in the CustomAttribs of the class, //all other instance of this type would not longer use reflexion to init properly //but will fetch the dynamic initialisation method compiled for this precise type //TODO:measure speed gain. #region Delfault values Loading dynamic compilation DynamicMethod dm = null; ILGenerator il = null; dm = new DynamicMethod("dyn_loadDefValues", MethodAttributes.Family | MethodAttributes.FamANDAssem | MethodAttributes.NewSlot, CallingConventions.Standard, typeof(void),new Type[] {CompilerServices.TObject},thisType,true); il = dm.GetILGenerator(256); il.DeclareLocal(CompilerServices.TObject); il.Emit(OpCodes.Nop); //set local GraphicObject to root object passed as 1st argument il.Emit (OpCodes.Ldarg_0); il.Emit (OpCodes.Stloc_0); foreach (EventInfo ei in thisType.GetEvents(BindingFlags.Public | BindingFlags.Instance)) { string expression; if (!getDefaultEvent(ei, styling, out expression)) continue; //TODO:dynEventHandler could be cached somewhere, maybe a style instanciator class holding the styling delegate and bound to it. foreach (string exp in CompilerServices.splitOnSemiColumnOutsideAccolades(expression)) { string trimed = exp.Trim(); if (trimed.StartsWith ("{", StringComparison.OrdinalIgnoreCase)){ il.Emit (OpCodes.Ldloc_0);//load this as 1st arg of event Add //push eventInfo as 1st arg of compile il.Emit (OpCodes.Ldloc_0); il.Emit (OpCodes.Call, CompilerServices.miGetType); il.Emit (OpCodes.Ldstr, ei.Name);//push event name il.Emit (OpCodes.Call, CompilerServices.miGetEvent); //push expression as 2nd arg of compile il.Emit (OpCodes.Ldstr, trimed.Substring (1, trimed.Length - 2)); //push null as 3rd arg, currentNode, not known when instanciing il.Emit (OpCodes.Ldnull); il.Emit (OpCodes.Callvirt, CompilerServices.miCompileDynEventHandler); il.Emit (OpCodes.Castclass, ei.EventHandlerType); il.Emit (OpCodes.Callvirt, ei.AddMethod); }else Debug.WriteLine("error in styling, event not handled : " + trimed); } } foreach (PropertyInfo pi in thisType.GetProperties(BindingFlags.Public | BindingFlags.Instance)) { if (pi.GetSetMethod () == null) continue; object defaultValue; if (!getDefaultValue (pi, styling, out defaultValue)) continue; CompilerServices.EmitSetValue (il, pi, defaultValue); } il.Emit(OpCodes.Ret); #endregion try { Interface.DefaultValuesLoader[styleKey] = (Interface.LoaderInvoker)dm.CreateDelegate(typeof(Interface.LoaderInvoker)); Interface.DefaultValuesLoader[styleKey] (this); } catch (Exception ex) { throw new Exception ("Error applying style <" + styleKey + ">:", ex); } }
void emitLoader(Type crowType) { string tmpXml = ReadOuterXml(); il.Emit(OpCodes.Ldloc_0); //save current go onto the stack if child has to be added #region Template and ItemTemplates loading if (typeof(TemplatedControl).IsAssignableFrom(crowType)) { //if its a template, first read template elements using (IMLReader reader = new IMLReader(il, tmpXml)) { string templatePath = reader.GetAttribute("Template"); //string itemTemplatePath = reader.GetAttribute ("ItemTemplate"); List <string[]> itemTemplateIds = new List <string[]> (); bool inlineTemplate = false; reader.Read(); int depth = reader.Depth + 1; while (reader.Read()) { if (!reader.IsStartElement() || reader.Depth > depth) { continue; } if (reader.Name == "Template") { inlineTemplate = true; reader.Read(); readChildren(reader, crowType, true); } else if (reader.Name == "ItemTemplate") { string dataType = "default", datas = "", path = ""; while (reader.MoveToNextAttribute()) { if (reader.Name == "DataType") { dataType = reader.Value; } else if (reader.Name == "Data") { datas = reader.Value; } else if (reader.Name == "Path") { path = reader.Value; } } reader.MoveToElement(); using (IMLReader iTmp = new IMLReader(null, reader.ReadInnerXml())) { string uid = Guid.NewGuid().ToString(); Interface.Instantiators [uid] = new ItemTemplate(iTmp.RootType, iTmp.GetLoader(), dataType, datas); itemTemplateIds.Add(new string[] { dataType, uid, datas }); } } } if (!inlineTemplate) { reader.il.Emit(OpCodes.Ldloc_0); //Load this templateControl ref if (string.IsNullOrEmpty(templatePath)) { reader.il.Emit(OpCodes.Ldnull); //default template loading } else { reader.il.Emit(OpCodes.Ldarg_1); //load currentInterface reader.il.Emit(OpCodes.Ldstr, templatePath); //Load template path string reader.il.Emit(OpCodes.Callvirt, //call Interface.Load(path) typeof(Interface).GetMethod("Load", BindingFlags.Instance | BindingFlags.Public)); } reader.il.Emit(OpCodes.Callvirt, //load template crowType.GetMethod("loadTemplate", BindingFlags.Instance | BindingFlags.NonPublic)); } foreach (string[] iTempId in itemTemplateIds) { reader.il.Emit(OpCodes.Ldloc_0); //load TempControl ref reader.il.Emit(OpCodes.Ldfld, //load ItemTemplates dic field typeof(TemplatedGroup).GetField("ItemTemplates")); reader.il.Emit(OpCodes.Ldstr, iTempId[0]); //load key reader.il.Emit(OpCodes.Ldstr, iTempId[1]); //load value reader.il.Emit(OpCodes.Callvirt, typeof(Interface).GetMethod("GetItemTemplate")); reader.il.Emit(OpCodes.Callvirt, typeof(Dictionary <string, ItemTemplate>).GetMethod("set_Item", new Type[] { typeof(string), typeof(ItemTemplate) })); if (!string.IsNullOrEmpty(iTempId [2])) { //expand delegate creation reader.il.Emit(OpCodes.Ldloc_0); //load TempControl ref reader.il.Emit(OpCodes.Ldfld, //load ItemTemplates dic field typeof(TemplatedGroup).GetField("ItemTemplates")); reader.il.Emit(OpCodes.Ldstr, iTempId [0]); //load key reader.il.Emit(OpCodes.Callvirt, typeof(Dictionary <string, ItemTemplate>).GetMethod("get_Item", new Type[] { typeof(string) })); reader.il.Emit(OpCodes.Ldloc_0); //load root of treeView reader.il.Emit(OpCodes.Callvirt, typeof(ItemTemplate).GetMethod("CreateExpandDelegate")); } } } } #endregion using (IMLReader reader = new IMLReader(il, tmpXml)){ reader.Read(); #region Styling and default values loading if (reader.HasAttributes) { string style = reader.GetAttribute("Style"); if (!string.IsNullOrEmpty(style)) { PropertyInfo pi = crowType.GetProperty("Style"); CompilerServices.EmitSetValue(reader.il, pi, style); } } reader.il.Emit(OpCodes.Ldloc_0); reader.il.Emit(OpCodes.Callvirt, typeof(GraphicObject).GetMethod("loadDefaultValues")); #endregion #region Attributes reading if (reader.HasAttributes) { MethodInfo miAddBinding = typeof(GraphicObject).GetMethod("BindMember"); while (reader.MoveToNextAttribute()) { if (reader.Name == "Style") { continue; } MemberInfo mi = crowType.GetMember(reader.Name).FirstOrDefault(); if (mi == null) { throw new Exception("Member '" + reader.Name + "' not found in " + crowType.Name); } if (mi.MemberType == MemberTypes.Event) { CompilerServices.emitBindingCreation(reader.il, reader.Name, reader.Value); continue; } PropertyInfo pi = mi as PropertyInfo; if (pi == null) { throw new Exception("Member '" + reader.Name + "' not found in " + crowType.Name); } if (reader.Value.StartsWith("{")) { CompilerServices.emitBindingCreation(reader.il, reader.Name, reader.Value.Substring(1, reader.Value.Length - 2)); } else { CompilerServices.EmitSetValue(reader.il, pi, reader.Value); } } reader.MoveToElement(); } #endregion if (reader.IsEmptyElement) { reader.il.Emit(OpCodes.Pop); //pop saved ref to current object return; } readChildren(reader, crowType); } il.Emit(OpCodes.Pop); //pop saved ref to current object }