diff options
| author | jpbruyere <jp.bruyere@hotmail.com> | 2016-12-22 12:29:10 +0100 |
|---|---|---|
| committer | jpbruyere <jp.bruyere@hotmail.com> | 2016-12-22 12:29:10 +0100 |
| commit | 366e3e09cd941a4bb80afcba87157764b007770c (patch) | |
| tree | 9ecc8c044825ae06323641c2d2658f8b00900548 /src/IML | |
| parent | b21a20ca16bd342dfc609a5b25fb0fe63f992715 (diff) | |
Add in tree handler at end of parsing just after name resolution
Move several static func for emit in CompilerService class
modifié : src/CompilerServices/CompilerServices.cs
modifié : src/IML/BindingDefinition.cs
modifié : src/IML/Context.cs
modifié : src/Instantiator.cs
Diffstat (limited to 'src/IML')
| -rw-r--r-- | src/IML/BindingDefinition.cs | 2 | ||||
| -rw-r--r-- | src/IML/Context.cs | 89 |
2 files changed, 69 insertions, 22 deletions
diff --git a/src/IML/BindingDefinition.cs b/src/IML/BindingDefinition.cs index 2c3fecdc..59b45167 100644 --- a/src/IML/BindingDefinition.cs +++ b/src/IML/BindingDefinition.cs @@ -53,6 +53,8 @@ namespace Crow.IML public bool IsDataSourceBinding { get { return TargetNA == null; }} public bool IsTemplateBinding { get { return IsDataSourceBinding ? false : TargetNA.Count == 0; }} public bool HasUnresolvedTargetName { get { return !string.IsNullOrEmpty(TargetName); }} + public MemberAddress SourceMemberAddress { get { return new MemberAddress (SourceNA, SourceMember);}} + public MemberAddress TargetMemberAddress { get { return new MemberAddress (TargetNA, TargetMember);}} /// <summary> /// replace the target node address with corresponding named node address, and clear the target name once resolved diff --git a/src/IML/Context.cs b/src/IML/Context.cs index 393bab21..ec97c3d8 100644 --- a/src/IML/Context.cs +++ b/src/IML/Context.cs @@ -32,7 +32,7 @@ namespace Crow.IML public string DataSourceMember; } /// <summary> - /// Context while parsing IML + /// Context while parsing IML, this will store what's needed only while parsing and not during instancing /// </summary> public class Context { @@ -44,12 +44,15 @@ namespace Crow.IML //public SubNodeType curSubNodeType; public NodeStack nodesStack = new NodeStack (); + /// <summary> store addresses of named node for name resolution at end of parsing </summary> public Dictionary<string, List<NodeAddress>> Names = new Dictionary<string, List<NodeAddress>>(); - + /// <summary> Store non datasource binding (in tree and template) by origine and orig member </summary> public Dictionary<NodeAddress, Dictionary<string, List<MemberAddress>>> Bindings = new Dictionary<NodeAddress, Dictionary<string, List<MemberAddress>>>(); + /// <summary> Store binding with name in target, will be resolved at end of parsing </summary> public List<BindingDefinition> UnresolvedTargets = new List<BindingDefinition>(); + public Context (Type rootType) { RootType = rootType; @@ -97,33 +100,50 @@ namespace Crow.IML Names[name] = new List<NodeAddress>(); Names[name].Add(CurrentNodeAddress); } - public void ResolveNames (){ + public void ProcessBindingDefinition(){//TODO:methodinfo fetching is redundant with early parsing foreach (BindingDefinition bd in UnresolvedTargets) { - if (!Names.ContainsKey (bd.TargetName)) { - System.Diagnostics.Debug.WriteLine ("Target Name '" + bd.TargetName + "' not found"); - continue; - } - NodeAddress resolvedNA = null; - foreach (NodeAddress na in Names[bd.TargetName]) { - bool naMatch = true; - for (int i = 0; i < bd.TargetNA.Count; i++) { - if (bd.TargetNA [i] != na [i]) { - naMatch = false; - break; - } + if (bd.HasUnresolvedTargetName) { + try { + ResolveName (bd); + } catch (Exception ex) { + System.Diagnostics.Debug.WriteLine (ex.ToString ()); + continue; } - if (naMatch) { - resolvedNA = na; + } + + MemberInfo miSource = bd.SourceMemberAddress.member; + if (miSource == null) + throw new Exception ("Source member '" + bd.SourceMember + "' not found"); + if (miSource.MemberType == MemberTypes.Event) + emitHandlerMethodAddition (bd, miSource as EventInfo); + else + StorePropertyBinding (bd); + } + } + public void ResolveName (BindingDefinition bd){ + + if (!Names.ContainsKey (bd.TargetName)) + throw new Exception ("Target Name '" + bd.TargetName + "' not found"); + + NodeAddress resolvedNA = null; + foreach (NodeAddress na in Names[bd.TargetName]) { + bool naMatch = true; + for (int i = 0; i < bd.TargetNA.Count; i++) { + if (bd.TargetNA [i] != na [i]) { + naMatch = false; break; } } - if (resolvedNA == null) - System.Diagnostics.Debug.WriteLine ("Target Name '" + bd.TargetName + "' not found"); - else { - bd.ResolveTargetName (resolvedNA); - StorePropertyBinding (bd); + if (naMatch) { + resolvedNA = na; + break; } } + + if (resolvedNA == null) + throw new Exception ("Target Name '" + bd.TargetName + "' not found"); + + bd.ResolveTargetName (resolvedNA); } void initILGen () @@ -144,5 +164,30 @@ namespace Crow.IML il.Emit(OpCodes.Callvirt, typeof(List<Delegate>).GetMethod("get_Item", new Type[] { typeof(Int32) })); il.Emit(OpCodes.Callvirt, evt.AddMethod);//call add event } + /// <summary> + /// Emits the handler method addition, done at end of parsing, Loc_0 is root node instance + /// </summary> + /// <param name="bd">Bd.</param> + /// <param name="evt">passed as arg to prevent refetching it for the 3rd time</param> + public void emitHandlerMethodAddition(BindingDefinition bd, EventInfo evt){ + //fetch source instance with address for handler addition (as 1st arg of handler.add) + il.Emit (OpCodes.Ldloc_0);//push root + CompilerServices.emitGetInstance (il, bd.SourceNA); + + //load handlerType of sourceEvent to create handler delegate (1st arg) + il.Emit (OpCodes.Ldtoken, evt.EventHandlerType); + il.Emit (OpCodes.Call, CompilerServices.miGetTypeFromHandle); + //load target the where the method is defined (2nd arg) + il.Emit (OpCodes.Ldloc_0); + CompilerServices.emitGetInstance (il, bd.TargetNA); + //load methodInfo (3rd arg) + il.Emit (OpCodes.Ldtoken, bd.TargetMemberAddress.member as MethodInfo); + il.Emit (OpCodes.Call, CompilerServices.miGetTypeFromHandle); + + il.Emit (OpCodes.Callvirt, typeof(Delegate).GetMethod ("CreateDelegate", + new Type[] { typeof(Type), typeof(object), typeof(MethodInfo) }));//create bound delegate + + il.Emit (OpCodes.Callvirt, evt.AddMethod);//call add event + } } }
\ No newline at end of file |