aboutsummaryrefslogtreecommitdiffstatsci
path: root/src/IML
diff options
context:
space:
mode:
authorjpbruyere <jp.bruyere@hotmail.com>2016-11-19 11:16:01 +0100
committerjpbruyere <jp.bruyere@hotmail.com>2016-11-19 11:16:01 +0100
commit4fb8b3a075bd8232be6fdcbb1f5a3b45265d33b4 (patch)
tree766be5b33f22c7c9097c0ca5545fe8c24a58c78a /src/IML
parentadbb4fd07a7c7ed236553d928be25c41c7106c27 (diff)
basic datasource binding functional without inititial set value during dschanged
Diffstat (limited to 'src/IML')
-rw-r--r--src/IML/Context.cs24
-rw-r--r--src/IML/MemberAddress.cs56
-rw-r--r--src/IML/NodeAddress.cs2
-rw-r--r--src/IML/Reader.cs251
4 files changed, 73 insertions, 260 deletions
diff --git a/src/IML/Context.cs b/src/IML/Context.cs
index e5bad2d4..44a9018b 100644
--- a/src/IML/Context.cs
+++ b/src/IML/Context.cs
@@ -26,6 +26,11 @@ using System.Xml;
namespace Crow.IML
{
+ public class DataSourceBinding {
+ public bool TwoWay;
+ public MemberAddress Source;
+ public string DataSourceMember;
+ }
/// <summary>
/// Context while parsing IML
/// </summary>
@@ -42,23 +47,34 @@ namespace Crow.IML
public Dictionary<string, string> Names = new Dictionary<string, string> ();
public Dictionary<string, Dictionary<string, MemberAddress>> PropertyBindings = new Dictionary<string, Dictionary<string, MemberAddress>> ();
+ public Dictionary<NodeAddress, Dictionary<string, MemberAddress>> Bindings =
+ new Dictionary<NodeAddress, Dictionary<string, MemberAddress>>();
+ public List<DataSourceBinding> DataSourceBindings = new List<DataSourceBinding>();
+
public Context (Type rootType)
{
RootType = rootType;
dm = new DynamicMethod ("dyn_instantiator",
- MethodAttributes.Family | MethodAttributes.FamANDAssem | MethodAttributes.NewSlot,
- CallingConventions.Standard,
- typeof (void), new Type [] { typeof (object), typeof (Interface) }, RootType, true);
+ typeof (void), new Type [] { typeof (Instantiator), typeof (object), typeof (Interface) }, true);
il = dm.GetILGenerator (256);
initILGen ();
}
+
+ public NodeAddress CurrentNodeAddress {
+ get {
+ NodeAddress tmp = new NodeAddress(nodesStack.ToArray ());
+ tmp.Add (CurrentNode);
+ return tmp;
+ }
+ }
+
void initILGen ()
{
il.DeclareLocal (typeof (GraphicObject));
il.Emit (OpCodes.Nop);
//set local GraphicObject to root object passed as 1st argument
- il.Emit (OpCodes.Ldarg_0);
+ il.Emit (OpCodes.Ldarg_1);
il.Emit (OpCodes.Stloc_0);
CompilerServices.emitSetCurInterface (il);
}
diff --git a/src/IML/MemberAddress.cs b/src/IML/MemberAddress.cs
index 85a346e4..89a293c3 100644
--- a/src/IML/MemberAddress.cs
+++ b/src/IML/MemberAddress.cs
@@ -19,20 +19,44 @@
// You should have received a copy of the GNU General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
using System;
+using System.Linq;
+using System.Reflection;
+
namespace Crow.IML
{
/// <summary>
/// Address member of a node
/// </summary>
public struct MemberAddress
- {
+ {
+ string memberName;
+ MemberInfo member;
public NodeAddress Address;
- public string Name;
- public MemberAddress (NodeAddress _address, string _member)
+// public string Name {
+// get { return memberName; }
+// set { memberName = value; }
+// }
+
+ public MemberAddress (NodeAddress _address, string _member, bool findMember = true)
+ {
+ Address = _address;
+ memberName = _member;
+ member = null;
+
+ if (!findMember)
+ return;
+ if (!tryFindMember ())
+ throw new Exception ("Member Not Found: " + memberName);
+ }
+ public MemberAddress (NodeAddress _address, MemberInfo _member)
{
Address = _address;
- Name = _member;
+ member = _member;
+ memberName = "";
+
+ if (member != null)
+ memberName = member.Name;
}
#region Equality Compare
@@ -42,16 +66,36 @@ namespace Crow.IML
}
public override int GetHashCode ()
{
- return Address.GetHashCode () ^ Name.GetHashCode ();
+ return Address.GetHashCode () ^ member.GetHashCode ();
}
public static bool operator == (MemberAddress x, MemberAddress y)
{
- return x.Address == y.Address && x.Name == y.Name;
+ return x.Address == y.Address && x.memberName == y.memberName;
}
public static bool operator != (MemberAddress x, MemberAddress y)
{
return !(x == y);
}
#endregion
+
+ bool tryFindMember ()
+ {
+ if (member != null)
+ throw new Exception ("member already found");
+ if (Address == null)
+ return false;
+ Type t = Address.LastOrDefault ().CrowType;
+ member = t.GetMember (memberName, BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance).FirstOrDefault ();
+
+ #region search for extensions methods if member not found in type
+ if (member == null && !string.IsNullOrEmpty (memberName)) {
+ Assembly a = Assembly.GetExecutingAssembly ();
+ string mn = memberName;
+ member = CompilerServices.GetExtensionMethods (a, t).Where (em => em.Name == mn).FirstOrDefault ();
+ }
+ #endregion
+
+ return member != null;
+ }
}
}
diff --git a/src/IML/NodeAddress.cs b/src/IML/NodeAddress.cs
index 95341ac7..12ecec38 100644
--- a/src/IML/NodeAddress.cs
+++ b/src/IML/NodeAddress.cs
@@ -26,6 +26,8 @@ namespace Crow.IML
{
public class NodeAddress : List<Node>
{
+ public NodeAddress (Node[] nodes) : base(nodes) {
+ }
public override bool Equals (object obj)
{
return obj is NodeAddress && this == obj as NodeAddress;
diff --git a/src/IML/Reader.cs b/src/IML/Reader.cs
index e4dbc3cb..7a0c8405 100644
--- a/src/IML/Reader.cs
+++ b/src/IML/Reader.cs
@@ -26,7 +26,7 @@ using System.Reflection.Emit;
using System.Linq;
using System.Collections.Generic;
-namespace Crow.IML
+namespace Crow.IML2
{
public class Reader : XmlTextReader
{
@@ -128,187 +128,14 @@ namespace Crow.IML
}
#endregion
- void createInstantiator(){
- context = new Context();
- RootType = findRootType();
- InitEmitter();
- emitLoader(RootType);
- Read();//close tag
- }
void createBindingDelegates(){
// foreach (Dictionary<string, MemberAddress> pb in IMLCtx.PropertyBindings) {
//
// }
}
- /// <summary>
- /// Inits il generator, RootType must have been read first
- /// </summary>
- void InitEmitter(){
-
- dm = new DynamicMethod("dyn_instantiator",
- MethodAttributes.Family | MethodAttributes.FamANDAssem | MethodAttributes.NewSlot,
- CallingConventions.Standard,
- typeof(void),new Type[] {typeof(object), typeof(Interface)}, RootType, true);
-
- context.il = dm.GetILGenerator(256);
- il.DeclareLocal(typeof(GraphicObject));
- il.Emit(OpCodes.Nop);
- //set local GraphicObject to root object passed as 1st argument
- il.Emit (OpCodes.Ldarg_0);
- il.Emit (OpCodes.Stloc_0);
- CompilerServices.emitSetCurInterface (il);
- }
- void emitLoader(Type crowType){
- Node expectedNode = new Node (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 (expectedNode.IsTemplate) {
- //if its a template, first read template elements
- using (Reader reader = new Reader (context, tmpXml)) {
- List<string []> itemTemplateIds = new List<string []> ();
- bool inlineTemplate = false;
-
- string templatePath = reader.GetAttribute ("Template");
-
- 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 ();
- context.nodesStack.Push (expectedNode);
- readChildren (reader);
- context.nodesStack.Pop();
- } 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 ();
-
- string itemTmpID;
-
- if (string.IsNullOrEmpty (path)) {
- using (Reader iTmp = new Reader (null, reader.ReadInnerXml ())) {
- itemTmpID = Guid.NewGuid ().ToString ();
- Interface.Instantiators [itemTmpID] =
- new ItemTemplate (iTmp.RootType, iTmp.GetLoader (), dataType, datas);
- }
- }else{
- if (!reader.IsEmptyElement)
- throw new Exception ("ItemTemplate with Path attribute may not include sub nodes");
- itemTmpID = path;
- Interface.Instantiators [itemTmpID] =
- new ItemTemplate (itemTmpID, dataType, datas);
- }
- itemTemplateIds.Add (new string[] { dataType, itemTmpID, datas });
- }
- }
-
- if (!inlineTemplate) {//load from path or default template
- reader.il.Emit (OpCodes.Ldloc_0);//Load current templatedControl 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)
- CompilerServices.miIFaceLoad);
- }
- reader.il.Emit (OpCodes.Callvirt, CompilerServices.miLoadTmp);//load template
- }
- //copy item templates (review this)
- foreach (string[] iTempId in itemTemplateIds) {
- reader.il.Emit (OpCodes.Ldloc_0);//load TempControl ref
- reader.il.Emit (OpCodes.Ldfld, CompilerServices.fldItemTemplates);//load ItemTemplates dic field
- reader.il.Emit (OpCodes.Ldstr, iTempId[0]);//load key
- reader.il.Emit (OpCodes.Ldstr, iTempId[1]);//load value
- reader.il.Emit (OpCodes.Callvirt, CompilerServices.miGetITemp);
- reader.il.Emit (OpCodes.Callvirt, CompilerServices.miAddITemp);
-
- if (!string.IsNullOrEmpty (iTempId [2])) {
- //expand delegate creation
- reader.il.Emit (OpCodes.Ldloc_0);//load TempControl ref
- reader.il.Emit (OpCodes.Ldfld, CompilerServices.fldItemTemplates);
- reader.il.Emit (OpCodes.Ldstr, iTempId [0]);//load key
- reader.il.Emit (OpCodes.Callvirt, CompilerServices.miGetITempFromDic);
- reader.il.Emit (OpCodes.Ldloc_0);//load root of treeView
- reader.il.Emit (OpCodes.Callvirt, CompilerServices.miCreateExpDel);
- }
- }
- }
- expectedNode.Index++;
- }
- #endregion
-
- using (Reader reader = new Reader (context, tmpXml)){
- reader.Read ();
-
- #region Styling and default values loading
- if (reader.HasAttributes) {
- string style = reader.GetAttribute ("Style");
- if (!string.IsNullOrEmpty (style))
- CompilerServices.EmitSetValue (reader.il, CompilerServices.piStyle, style);
- }
- reader.il.Emit (OpCodes.Ldloc_0);
- reader.il.Emit (OpCodes.Callvirt, CompilerServices.miLoadDefaultVals);
- #endregion
-
- #region Attributes reading
- if (reader.HasAttributes) {
-
- 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 (pi.Name == "Name")
- context.Names.Add(reader.Value, Node.AddressToString(context.nodesStack.ToArray()));
-
- if (reader.Value.StartsWith ("{", StringComparison.OrdinalIgnoreCase)) {
- readPropertyBinding(reader.Name, reader.Value.Substring (1, reader.Value.Length - 2));
- //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;
- }
- context.nodesStack.Push (expectedNode);
- readChildren (reader);
- context.nodesStack.Pop ();
- }
- il.Emit (OpCodes.Pop);//pop saved ref to current object
- }
void registerPropertyBinding(string origNode, string origProp, MemberAddress ma){
if (!context.PropertyBindings.ContainsKey(origNode))
context.PropertyBindings [origNode] = new Dictionary<string, MemberAddress> ();
@@ -390,83 +217,7 @@ namespace Crow.IML
registerPropertyBinding (nodeId, targetName, new MemberAddress (context.nodesStack.ToArray (), srcProperty));
}
- /// <summary>
- /// Parse child node an generate corresponding msil
- /// </summary>
- void readChildren(Reader reader){
- bool endTagReached = false;
- while (reader.Read()){
- switch (reader.NodeType) {
- case XmlNodeType.EndElement:
- endTagReached = true;
- break;
- case XmlNodeType.Element:
- //Templates
- if (reader.Name == "Template" ||
- reader.Name == "ItemTemplate") {
- reader.Skip ();
- continue;
- }
-
-
- //push current instance on stack for parenting
- //loc_0 will be used for child
- reader.il.Emit (OpCodes.Ldloc_0);
-
- Type t = Type.GetType ("Crow." + reader.Name);
- if (t == null) {
- Assembly a = Assembly.GetEntryAssembly ();
- foreach (Type expT in a.GetExportedTypes ()) {
- if (expT.Name == reader.Name)
- t = expT;
- }
- }
- if (t == null)
- throw new Exception (reader.Name + " type not found");
-
- reader.il.Emit (OpCodes.Newobj, t.GetConstructors () [0]);//TODO:search parameterless ctor
- reader.il.Emit (OpCodes.Stloc_0);//child is now loc_0
- CompilerServices.emitSetCurInterface (il);
-
- reader.emitLoader (t);
-
- reader.il.Emit (OpCodes.Ldloc_0);//load child on stack for parenting
- reader.il.Emit (OpCodes.Callvirt, miAddChild [(int)context.nodesStack.Peek ().Type -1]);
- reader.il.Emit (OpCodes.Stloc_0); //reset local to current go
- reader.il.Emit (OpCodes.Ldloc_0);//save current go onto the stack if child has to be added
- context.nodesStack.Peek ().Index++;
-
- break;
- }
- if (endTagReached)
- break;
- }
- }
- /// <summary>
- /// read first node to set GraphicObject class for loading
- /// and let reader position on that node
- /// </summary>
- Type findRootType ()
- {
- string root = "Object";
- while (Read()) {
- if (NodeType == XmlNodeType.Element) {
- root = this.Name;
- break;
- }
- }
-
- Type t = Type.GetType ("Crow." + root);
- if (t == null) {
- Assembly a = Assembly.GetEntryAssembly ();
- foreach (Type expT in a.GetExportedTypes ()) {
- if (expT.Name == root)
- t = expT;
- }
- }
- return t;
- }
}
}