namespace go
{
- public enum BindingType
+ public class MemberReference
{
- Handler,
- DynamicHandler,
- PropertyBinding
- }
- public class Binding{
- public MemberInfo SourceMember;
- public string Expression;
+ public object Instance;
+ public MemberInfo Member;
- public PropertyInfo Property { get { return SourceMember as PropertyInfo; } }
- public EventInfo Event { get { return SourceMember as EventInfo; } }
+ public PropertyInfo Property { get { return Member as PropertyInfo; } }
+ public FieldInfo Field { get { return Member as FieldInfo; } }
+ public EventInfo Event { get { return Member as EventInfo; } }
+ public MethodInfo Method { get { return Member as MethodInfo; } }
- public Binding(){
+ public MemberReference(){
}
- public Binding(MemberInfo _sourceMember, string _expression)
+ public MemberReference(object _instance, MemberInfo _member = null)
{
- SourceMember = _sourceMember;
- Expression = _expression;
+ Instance = _instance;
+ Member = _member;
+ }
+ public bool FindMember(string _memberName)
+ {
+ Type t = Instance.GetType ();
+ Member = t.GetMember (_memberName).FirstOrDefault ();
+
+ #region search for extensions methods if member not found in type
+ if (Member == null && !string.IsNullOrEmpty(_memberName))
+ {
+ Assembly a = Assembly.GetExecutingAssembly();
+ Member = CompilerServices.GetExtensionMethods(a, t).Where(em=>em.Name == _memberName).FirstOrDefault();
+ }
+ #endregion
+
+ return string.IsNullOrEmpty(_memberName) ? false : true;
}
}
+ public class Binding{
+ static int bindingCpt = 0;
+ string dynMethodId = "";
+ public string NewDynMethodId {
+ get {
+ if (!string.IsNullOrEmpty (dynMethodId))
+ return dynMethodId;
+ dynMethodId = "dynHandle_" + bindingCpt;
+ bindingCpt++;
+ return dynMethodId;
+ }
+ }
+ public string DynMethodId {
+ get { return dynMethodId; }
+ }
+
- public class ResolvedBinding
- {
- public object Target;
- public MemberInfo Member;
+ public MemberReference Source;
+ public MemberReference Target;
- public Binding Binding;
+ public string Expression;
- public ResolvedBinding(){
- }
- public ResolvedBinding(Binding _binding){
- Binding = _binding;
+ #region CTOR
+ public Binding(){}
+ public Binding(MemberReference _source, string _expression)
+ {
+ Source = _source;
+ Expression = _expression;
}
+ #endregion
- public bool FindTarget(GraphicObject source){
+ public bool FindTarget(){
string member = null;
//if binding exp = '{}' => binding is done on datasource
- if (string.IsNullOrEmpty (Binding.Expression)) {
- Target = source;
- Member = null;
+ if (string.IsNullOrEmpty (Expression)) {
+ Target = new MemberReference (Source.Instance);
return true;
}
- //if (Binding.SourceMember.MemberType == MemberTypes.Event)
-
- string[] bindingExp = Binding.Expression.Split ('/');
+ string[] bindingExp = Expression.Split ('/');
if (bindingExp.Length == 1) {
//datasource binding
- Target = source.DataSource;
+ Target = new MemberReference((Source.Instance as GraphicObject).DataSource);
member = bindingExp [0];
} else {
int ptr = 0;
- ILayoutable tmp = source;
+ ILayoutable tmp = Source.Instance as ILayoutable;
if (string.IsNullOrEmpty (bindingExp [0])) {
//if exp start with '/' => Graphic tree parsing start at top container
- tmp = source.TopContainer as ILayoutable;
+ tmp = tmp.TopContainer as ILayoutable;
ptr++;
}
while (ptr < bindingExp.Length - 1) {
else if (bindingExp [ptr] == ".") {
if (ptr > 0)
throw new Exception ("Syntax error in binding, './' may only appear in first position");
- tmp = source;
+ tmp = Source.Instance as ILayoutable;
}else
tmp = (tmp as GraphicObject).FindByName (bindingExp [ptr]);
ptr++;
member = bindTrg [1];
} else
throw new Exception ("Syntax error in binding, expected 'go dot member'");
-
- Target = tmp;
- }
- if (Target == null) {
- Debug.WriteLine ("Binding Source is null: " + Binding.Expression);
- return false;
- }
- Type targetType = Target.GetType ();
- Member = targetType.GetMember (member).FirstOrDefault ();
- #region search for extensions methods if member not found in type
- if (Member == null && !string.IsNullOrEmpty(member))
- {
- Assembly a = Assembly.GetExecutingAssembly();
- Member = CompilerServices.GetExtensionMethods(a, targetType).FirstOrDefault();
+ Target = new MemberReference(tmp);
}
- #endregion
-
- if (member == null) {
- Debug.WriteLine ("Binding member not found: " + member);
+ if (Target == null) {
+ Debug.WriteLine ("Binding Source is null: " + Expression);
return false;
}
- return true;
+ if (Target.FindMember (member))
+ return true;
+
+ Debug.WriteLine ("Binding member not found: " + member);
+ return false;
}
- }
-
- public static class CompilerServices2
- {
- static int dynHandleCpt = 0;
- /// <summary>
- /// Compile events expression in GOML attributes
- /// </summary>
- /// <param name="es">Event binding details</param>
- public static void ResolveBinding(DynAttribute es)
+ public void Reset()
{
- Type srcType = es.Source.GetType ();
-
- #region Retrieve EventHandler parameter type
- EventInfo ei = srcType.GetEvent (es.MemberName);
- MethodInfo invoke = ei.EventHandlerType.GetMethod ("Invoke");
- ParameterInfo[] pars = invoke.GetParameters ();
-
- Type handlerArgsType = pars [1].ParameterType;
- #endregion
-
- Type[] args = {typeof(object), handlerArgsType};
- DynamicMethod dm = new DynamicMethod("dynHandle_" + dynHandleCpt,
- typeof(void),
- args,
- srcType.Module);
-
- es.Source.DynamicMethodIds.Add (dynHandleCpt);
-
- dynHandleCpt++;
-
- #region IL generation
- ILGenerator il = dm.GetILGenerator(256);
-
- string src = es.Value.Trim();
-
- if (! (src.StartsWith("{") || src.EndsWith ("}")))
- throw new Exception (string.Format("GOML:Malformed {0} Event handler: {1}", es.MemberName, es.Value));
-
- src = src.Substring (1, src.Length - 2);
- string[] srcLines = src.Split (new char[] { ';' });
-
- foreach (string srcLine in srcLines) {
- string statement = srcLine.Trim ();
-
- string[] operandes = statement.Split (new char[] { '=' });
- if (operandes.Length < 2) //not an affectation
- {
- continue;
- }
- string lop = operandes [0].Trim ();
- string rop = operandes [operandes.Length-1].Trim ();
-
- #region LEFT OPERANDES
- GraphicObject lopObj = es.Source; //default left operand base object is
- //the first arg (object sender) of the event handler
-
- string[] lopParts = lop.Split (new char[] { '.' });
- if (lopParts.Length == 2) {//should search also for member of es.Source
- lopObj = es.Source.FindByName (lopParts [0]);
- if (lopObj==null)
- throw new Exception (string.Format("GOML:Unknown name: {0}", lopParts[0]));
- //TODO: should create private member holding ref of lopObj, and emit
- //a call to FindByName(lopObjName) during #ctor or in a onLoad func or evt handler
- throw new Exception (string.Format("GOML:obj tree ref not yet implemented", lopParts[0]));
- }else
- il.Emit(OpCodes.Ldarg_0); //load sender ref onto the stack
-
- int i = lopParts.Length -1;
-
- MemberInfo lopMbi = lopObj.GetType().GetMember (lopParts[i])[0];
- OpCode lopSetOC;
- dynamic lopSetMbi;
- Type lopT = null;
- switch (lopMbi.MemberType) {
- case MemberTypes.Property:
- PropertyInfo lopPi = srcType.GetProperty (lopParts[i]);
- MethodInfo dstMi = lopPi.GetSetMethod ();
- lopT = lopPi.PropertyType;
- lopSetMbi = dstMi;
- lopSetOC = OpCodes.Callvirt;
- break;
- case MemberTypes.Field:
- FieldInfo dstFi = srcType.GetField(lopParts[i]);
- lopT = dstFi.FieldType;
- lopSetMbi = dstFi;
- lopSetOC = OpCodes.Stfld;
- break;
- default:
- throw new Exception (string.Format("GOML:member type not handle: {0}", lopParts[i]));
- }
- #endregion
-
- #region RIGHT OPERANDES
- if (rop.StartsWith("\'")){
- if (!rop.EndsWith("\'"))
- throw new Exception (string.Format
- ("GOML:malformed string constant in handler: {0}", rop));
- string strcst = rop.Substring (1, rop.Length - 2);
-
- il.Emit(OpCodes.Ldstr,strcst);
-
- }else{
- //search for a static field in left operand type named 'rop name'
- FieldInfo ropFi = lopT.GetField (rop, BindingFlags.Static|BindingFlags.Public);
- if (ropFi != null)
- {
- il.Emit (OpCodes.Ldsfld, ropFi);
- }else{
- //search if parsing methods are present
- MethodInfo lopTryParseMi = lopT.GetMethod("TryParse");
-
- }
- }
-
- #endregion
-
- //emit left operand assignment
- il.Emit(lopSetOC, lopSetMbi);
- }
+ Target = null;
+ dynMethodId = "";
+ }
+ }
- il.Emit(OpCodes.Ret);
- #endregion
- Delegate del = dm.CreateDelegate(ei.EventHandlerType);
- MethodInfo addHandler = ei.GetAddMethod ();
- addHandler.Invoke(es.Source, new object[] {del});
- }
-
- }
public static class CompilerServices
{
- public static void CreateBindingHandler()
- {
- }
-
static int dynHandleCpt = 0;
- /// <summary>
- /// Compile events expression in GOML attributes
- /// </summary>
- /// <param name="es">Event binding details</param>
- public static void CompileEventSource(DynAttribute es)
- {
- Type srcType = es.Source.GetType ();
-
- #region Retrieve EventHandler parameter type
- EventInfo ei = srcType.GetEvent (es.MemberName);
- MethodInfo invoke = ei.EventHandlerType.GetMethod ("Invoke");
- ParameterInfo[] pars = invoke.GetParameters ();
-
- Type handlerArgsType = pars [1].ParameterType;
- #endregion
-
- Type[] args = {typeof(object), handlerArgsType};
- DynamicMethod dm = new DynamicMethod("dynHandle",
- typeof(void),
- args,
- srcType.Module);
-
- #region IL generation
- ILGenerator il = dm.GetILGenerator(256);
-
- string src = es.Value.Trim();
-
- if (! (src.StartsWith("{") || src.EndsWith ("}")))
- throw new Exception (string.Format("GOML:Malformed {0} Event handler: {1}", es.MemberName, es.Value));
-
- src = src.Substring (1, src.Length - 2);
- string[] srcLines = src.Split (new char[] { ';' });
-
- foreach (string srcLine in srcLines) {
- string statement = srcLine.Trim ();
-
- string[] operandes = statement.Split (new char[] { '=' });
- if (operandes.Length < 2) //not an affectation
- {
- continue;
- }
- string lop = operandes [0].Trim ();
- string rop = operandes [operandes.Length-1].Trim ();
-
- #region LEFT OPERANDES
- GraphicObject lopObj = es.Source; //default left operand base object is
- //the first arg (object sender) of the event handler
-
- string[] lopParts = lop.Split (new char[] { '.' });
- if (lopParts.Length == 2) {//should search also for member of es.Source
- lopObj = es.Source.FindByName (lopParts [0]);
- if (lopObj==null)
- throw new Exception (string.Format("GOML:Unknown name: {0}", lopParts[0]));
- //TODO: should create private member holding ref of lopObj, and emit
- //a call to FindByName(lopObjName) during #ctor or in a onLoad func or evt handler
- throw new Exception (string.Format("GOML:obj tree ref not yet implemented", lopParts[0]));
- }else
- il.Emit(OpCodes.Ldarg_0); //load sender ref onto the stack
-
- int i = lopParts.Length -1;
-
- MemberInfo lopMbi = lopObj.GetType().GetMember (lopParts[i])[0];
- OpCode lopSetOC;
- dynamic lopSetMbi;
- Type lopT = null;
- switch (lopMbi.MemberType) {
- case MemberTypes.Property:
- PropertyInfo lopPi = srcType.GetProperty (lopParts[i]);
- MethodInfo dstMi = lopPi.GetSetMethod ();
- lopT = lopPi.PropertyType;
- lopSetMbi = dstMi;
- lopSetOC = OpCodes.Callvirt;
- break;
- case MemberTypes.Field:
- FieldInfo dstFi = srcType.GetField(lopParts[i]);
- lopT = dstFi.FieldType;
- lopSetMbi = dstFi;
- lopSetOC = OpCodes.Stfld;
- break;
- default:
- throw new Exception (string.Format("GOML:member type not handle: {0}", lopParts[i]));
- }
- #endregion
-
- #region RIGHT OPERANDES
- if (rop.StartsWith("\'")){
- if (!rop.EndsWith("\'"))
- throw new Exception (string.Format
- ("GOML:malformed string constant in handler: {0}", rop));
- string strcst = rop.Substring (1, rop.Length - 2);
-
- il.Emit(OpCodes.Ldstr,strcst);
-
- }else{
- //search for a static field in left operand type named 'rop name'
- FieldInfo ropFi = lopT.GetField (rop, BindingFlags.Static|BindingFlags.Public);
- if (ropFi != null)
- {
- il.Emit (OpCodes.Ldsfld, ropFi);
- }else{
- //search if parsing methods are present
- MethodInfo lopTryParseMi = lopT.GetMethod("TryParse");
- //TODO
- }
- }
-
- #endregion
-
- //emit left operand assignment
- il.Emit(lopSetOC, lopSetMbi);
- }
-
- il.Emit(OpCodes.Ret);
-
- #endregion
-
- Delegate del = dm.CreateDelegate(ei.EventHandlerType);
- MethodInfo addHandler = ei.GetAddMethod ();
- addHandler.Invoke(es.Source, new object[] {del});
- }
-
- /// <summary>
- /// Resolves GOML property bindings afler loading
- /// </summary>
- /// <param name="binding">Binding details</param>
- /// <param name="_source">Data source for binding</param>
- public static void ResolveBinding(DynAttribute binding, object _source)
- {
- object srcGO = null;
- string statement = binding.Value;
-
- if (statement.StartsWith ("/"))//binding is done in graphic object tree, _source param is ignore
- srcGO = binding.Source;
- else
- srcGO = _source;
-
- string[] bindingExp = binding.Value.Split ('/');
-
- if (bindingExp.Length > 1){
- int i = 0;
- srcGO = binding.Source; //starts parsing from current GO
- while (i < bindingExp.Length - 1) {
- if (bindingExp [i] == "..")
- srcGO = (srcGO as ILayoutable).Parent as GraphicObject;
- else
- srcGO = (srcGO as GraphicObject).FindByName (bindingExp [i]);
- i++;
- }
- string[] bindTrg = bindingExp [i].Split ('.');
-
- if (bindTrg.Length == 2) {
- srcGO = (srcGO as GraphicObject).FindByName (bindTrg [0]);
- statement = bindTrg [1];
- } else
- throw new Exception ("Syntax error in binding, expected 'go dot member'");
- }
-
- if (srcGO == null) {
- Debug.WriteLine ("Invalid Binding Source: " + binding.Value);
- return;
- }
- Type srcType = srcGO.GetType ();
- Type dstType = binding.Source.GetType ();
-
- MemberInfo miSrc = srcType.GetMember (statement).FirstOrDefault ();
- MemberInfo miDst = dstType.GetMember (binding.MemberName).FirstOrDefault ();
-
- object srcVal = null; //value in source member
-
- #region search for extensions methods if member not found in type
- if (miSrc == null && !string.IsNullOrEmpty(statement))
- {
- Assembly a = Assembly.GetExecutingAssembly();
- miSrc = CompilerServices.GetExtensionMethods(a, srcType).FirstOrDefault();
- }
- #endregion
-
- #region initialize target with actual value
-
- if (string.IsNullOrEmpty(binding.Value))
- srcVal = srcGO;//if no member is provided for binding, source raw value is taken
- else if (miSrc != null){
- if (miSrc.MemberType == MemberTypes.Property)
- srcVal = (miSrc as PropertyInfo).GetGetMethod ().Invoke (srcGO, null);
- else if (miSrc.MemberType == MemberTypes.Field)
- srcVal = (miSrc as FieldInfo).GetValue (srcGO);
- else if (miSrc.MemberType == MemberTypes.Method){
- MethodInfo mthSrc = miSrc as MethodInfo;
- if (mthSrc.IsDefined(typeof(ExtensionAttribute), false))
- srcVal = mthSrc.Invoke(null, new object[] {srcGO});
- else
- srcVal = mthSrc.Invoke(srcGO, null);
- }else
- throw new Exception ("unandled source member type for binding");
- }
-// if (miSrc != null){
- if (miDst.MemberType == MemberTypes.Property) {
- PropertyInfo piDst = miDst as PropertyInfo;
- //TODO: handle other dest type conversions
- if (piDst.PropertyType == typeof(string)){
- if (srcVal != null)
- srcVal = srcVal.ToString ();
- }
- piDst.GetSetMethod ().Invoke (binding.Source, new object[] { srcVal });
- } else if (miDst.MemberType == MemberTypes.Field) {
- FieldInfo fiDst = miDst as FieldInfo;
- if (fiDst.FieldType == typeof(string))
- srcVal = srcVal.ToString ();
- fiDst.SetValue (binding.Source, srcVal );
- }else
- throw new Exception("unandled destination member type for binding");
-// }
- #endregion
-
- #region Retrieve EventHandler parameter type
- EventInfo ei = srcType.GetEvent ("ValueChanged");
- if (ei == null)
- return; //no dynamic update if ValueChanged interface is not implemented
-
- MethodInfo evtInvoke = ei.EventHandlerType.GetMethod ("Invoke");
- ParameterInfo[] evtParams = evtInvoke.GetParameters ();
- Type handlerArgsType = evtParams [1].ParameterType;
-
- #endregion
-
-
- Type[] args = {typeof(object), handlerArgsType};
- DynamicMethod dm = new DynamicMethod("dynHandle_" + dynHandleCpt,
- typeof(void),
- args,
- srcType.Module, true);
-
- (binding.Source as GraphicObject).DynamicMethodIds.Add (dynHandleCpt);
-
- dynHandleCpt++;
-
- //register target object reference
- int dstIdx = Interface.Reference(binding.Source);
-
- #region IL generation
- ILGenerator il = dm.GetILGenerator(256);
-
- System.Reflection.Emit.Label labFailed = il.DefineLabel();
- System.Reflection.Emit.Label labContinue = il.DefineLabel();
-
- #region test if valueChange event is the correct one
- il.Emit (OpCodes.Ldstr, statement);
- //push name from arg
- il.Emit(OpCodes.Ldarg_1);
- FieldInfo fiMbName = typeof(ValueChangeEventArgs).GetField("MemberName");
- il.Emit(OpCodes.Ldfld, fiMbName);
- MethodInfo miStrEqu = typeof(string).GetMethod("op_Inequality", new Type[] {typeof(string),typeof(string)});
- il.Emit(OpCodes.Call, miStrEqu);
- il.Emit(OpCodes.Brfalse_S, labContinue);
- il.Emit(OpCodes.Br_S, labFailed);
- il.MarkLabel(labContinue);
- #endregion
-
-// string[] srcLines = binding.Value.Trim().Split (new char[] { ';' });
-// foreach (string srcLine in srcLines) {
- //MethodInfo infoWriteLine = typeof(System.Diagnostics.Debug).GetMethod("WriteLine", new Type[] { typeof(string) });
-
-
- //load target ref onto the stack
- FieldInfo fiRefs = typeof(Interface).GetField("References");
- il.Emit(OpCodes.Ldsfld, fiRefs);
- il.Emit(OpCodes.Ldc_I4, dstIdx);
- MethodInfo miGetRef = Interface.References.GetType().GetMethod("get_Item");
- il.Emit(OpCodes.Callvirt, miGetRef);
- il.Emit(OpCodes.Isinst, dstType);
-
- //push new value
- il.Emit(OpCodes.Ldarg_1);
- FieldInfo fiNewValue = typeof(ValueChangeEventArgs).GetField("NewValue");
- il.Emit(OpCodes.Ldfld, fiNewValue);
-
- //Target is expected always to be a Property
- PropertyInfo piTarget = dstType.GetProperty(binding.MemberName);
-
- //type of the source value
- Type srcValueType = null;
-
- //member info of the source value
- MemberInfo miSrcVal = miSrc;
-
- //this allow memberless binding with only a name passed as MemberName
- //the type of the source value is determined by the destination member
- if (miSrcVal == null)
- miSrcVal = miDst;
-
- if (miSrcVal.MemberType == MemberTypes.Property)
- srcValueType = (miSrcVal as PropertyInfo).PropertyType;
- else if (miSrcVal.MemberType == MemberTypes.Field)
- srcValueType = (miSrcVal as FieldInfo).FieldType;
- else
- throw new Exception("unandled source member type for binding");
-
- if (!srcValueType.IsValueType)
- il.Emit(OpCodes.Castclass, srcValueType);
- else if (piTarget.PropertyType != srcValueType)
- il.Emit(OpCodes.Callvirt, GetConvertMethod( piTarget.PropertyType ));
- else
- il.Emit(OpCodes.Unbox_Any, piTarget.PropertyType);
-
- il.Emit(OpCodes.Callvirt, piTarget.GetSetMethod());
-
- il.MarkLabel(labFailed);
- il.Emit(OpCodes.Ret);
-
- #endregion
-
- Delegate del = dm.CreateDelegate(ei.EventHandlerType);
- MethodInfo addHandler = ei.GetAddMethod ();
- addHandler.Invoke(srcGO, new object[] {del});
- }
-
#region conversions
internal static MethodInfo GetConvertMethod( Type targetType )
{ \r
public class GraphicObject : IXmlSerializable, ILayoutable, IValueChange\r
{\r
- internal List<int> DynamicMethodIds = new List<int> ();\r
+ internal List<string> DynamicMethodIds\r
+ {\r
+ get { return Bindings.\r
+ Where(bi=>!string.IsNullOrEmpty(bi.DynMethodId)).\r
+ Select (b => b.DynMethodId).ToList ();\r
+ }\r
+ }\r
internal List<Binding> Bindings = new List<Binding> ();\r
\r
#region IValueChange implementation\r
\r
public virtual void ResolveBindings()\r
{\r
- List<ResolvedBinding> resolved = new List<ResolvedBinding> ();\r
+ List<Binding> resolved = new List<Binding> ();\r
foreach (Binding b in Bindings) {\r
- if (b.SourceMember.MemberType == MemberTypes.Event) {\r
+ if (b.Source.Member.MemberType == MemberTypes.Event) {\r
if (b.Expression.StartsWith("{")){\r
CompileEventSource(b);\r
continue;\r
}\r
}\r
- ResolvedBinding rb = new ResolvedBinding (b);\r
- if (!rb.FindTarget (this))\r
+ if (!b.FindTarget ())\r
continue;\r
- if (rb.Binding.SourceMember.MemberType == MemberTypes.Event) {\r
+ if (b.Source.Member.MemberType == MemberTypes.Event) {\r
//register handler for event\r
- MethodInfo mi = rb.Member as MethodInfo;\r
- if (mi == null) {\r
- Debug.WriteLine ("Handler Method not found: " + rb.Binding.Expression);\r
+ if (b.Target.Method == null) {\r
+ Debug.WriteLine ("Handler Method not found: " + b.Expression);\r
continue;\r
}\r
\r
- MethodInfo addHandler = rb.Binding.Event.GetAddMethod ();\r
- Delegate del = Delegate.CreateDelegate (rb.Binding.Event.EventHandlerType, rb.Target, mi);\r
+ MethodInfo addHandler = b.Source.Event.GetAddMethod ();\r
+ Delegate del = Delegate.CreateDelegate (b.Source.Event.EventHandlerType, b.Target.Instance, b.Target.Method);\r
addHandler.Invoke (this, new object[] { del });\r
continue;\r
}\r
- resolved.Add (rb); \r
+ resolved.Add (b); \r
}\r
//group;only one dynMethods by target (valuechanged event source)\r
//changed value name tested in switch\r
- IEnumerable<ResolvedBinding[]> groupedByTarget = resolved.GroupBy (g => g.Target, g => g, (k, g) => g.ToArray ());\r
- foreach (ResolvedBinding[] grouped in groupedByTarget) {\r
+ IEnumerable<Binding[]> groupedByTarget = resolved.GroupBy (g => g.Target.Instance, g => g, (k, g) => g.ToArray ());\r
+ foreach (Binding[] grouped in groupedByTarget) {\r
int i = 0;\r
- Type targetType = grouped[0].Target.GetType();\r
+ Type targetType = grouped[0].Target.Instance.GetType();\r
Type sourceType = this.GetType();\r
\r
DynamicMethod dm = null;\r
LocalBuilder lbMemberName = null;\r
LocalBuilder lbValue = null;\r
\r
+\r
+\r
#region Retrieve EventHandler parameter type\r
EventInfo ei = targetType.GetEvent ("ValueChanged");\r
//no dynamic update if ValueChanged interface is not implemented\r
Type handlerArgsType = evtParams [1].ParameterType;\r
\r
Type[] args = {typeof(object), typeof(object),handlerArgsType};\r
- dm = new DynamicMethod("dynHandle",\r
+ dm = new DynamicMethod(grouped[0].NewDynMethodId,\r
typeof(void), \r
args,\r
sourceType);\r
#endregion\r
\r
i = 0;\r
- foreach (ResolvedBinding rb in grouped) {\r
+ foreach (Binding b in grouped) {\r
#region initialize target with actual value\r
object targetValue = null;\r
- if (rb.Member != null){\r
- if (rb.Member.MemberType == MemberTypes.Property)\r
- targetValue = (rb.Member as PropertyInfo).GetGetMethod ().Invoke (rb.Target, null);\r
- else if (rb.Member.MemberType == MemberTypes.Field)\r
- targetValue = (rb.Member as FieldInfo).GetValue (rb.Target);\r
- else if (rb.Member.MemberType == MemberTypes.Method){\r
- MethodInfo mthSrc = rb.Member as MethodInfo;\r
+ if (b.Target.Member != null){\r
+ if (b.Target.Member.MemberType == MemberTypes.Property)\r
+ targetValue = b.Target.Property.GetGetMethod ().Invoke (b.Target.Instance, null);\r
+ else if (b.Target.Member.MemberType == MemberTypes.Field)\r
+ targetValue = b.Target.Field.GetValue (b.Target.Instance);\r
+ else if (b.Target.Member.MemberType == MemberTypes.Method){\r
+ MethodInfo mthSrc = b.Target.Method;\r
if (mthSrc.IsDefined(typeof(ExtensionAttribute), false))\r
- targetValue = mthSrc.Invoke(null, new object[] {rb.Target});\r
+ targetValue = mthSrc.Invoke(null, new object[] {b.Target.Instance});\r
else\r
- targetValue = mthSrc.Invoke(rb.Target, null);\r
+ targetValue = mthSrc.Invoke(b.Target.Instance, null);\r
}else\r
throw new Exception ("unandled source member type for binding"); \r
- }else if (string.IsNullOrEmpty(rb.Binding.Expression))\r
+ }else if (string.IsNullOrEmpty(b.Expression))\r
targetValue= grouped [0].Target;//empty binding exp=> bound to target object by default\r
//TODO: handle other dest type conversions\r
- if (rb.Binding.Property.PropertyType == typeof(string)){\r
+ if (b.Source.Property.PropertyType == typeof(string)){\r
if (targetValue == null){\r
//set default value\r
\r
}else\r
targetValue = targetValue.ToString ();\r
}\r
- rb.Binding.Property.GetSetMethod ().Invoke (this, new object[] { targetValue });\r
+ b.Source.Property.GetSetMethod ().Invoke (this, new object[] { targetValue });\r
#endregion\r
\r
//if no dyn update, skip jump table\r
continue;\r
\r
il.Emit (OpCodes.Ldloc_0);\r
- if (rb.Member != null)\r
- il.Emit (OpCodes.Ldstr, rb.Member.Name);\r
+ if (b.Target.Member != null)\r
+ il.Emit (OpCodes.Ldstr, b.Target.Member.Name);\r
else\r
- il.Emit (OpCodes.Ldstr, rb.Binding.Expression);\r
+ il.Emit (OpCodes.Ldstr, b.Expression);\r
il.Emit (OpCodes.Callvirt, stringEquals);\r
il.Emit (OpCodes.Brtrue, jumpTable[i]);\r
i++;\r
il.Emit (OpCodes.Br, endMethod);\r
\r
i = 0;\r
- foreach (ResolvedBinding rb in grouped) {\r
+ foreach (Binding b in grouped) {\r
\r
il.MarkLabel (jumpTable [i]);\r
il.Emit(OpCodes.Ldloc_1);\r
//by default, target value type is deducted from source member type to allow\r
//memberless binding, if targetMember exists, it will be used to determine target\r
//value type for conversion\r
- Type targetValueType = rb.Binding.Property.PropertyType;\r
- if (rb.Member != null) {\r
- if (rb.Member.MemberType == MemberTypes.Property)\r
- targetValueType = (rb.Member as PropertyInfo).PropertyType;\r
- else if (rb.Member.MemberType == MemberTypes.Field)\r
- targetValueType = (rb.Member as FieldInfo).FieldType;\r
+ Type targetValueType = b.Source.Property.PropertyType;\r
+ if (b.Target.Member != null) {\r
+ if (b.Target.Member.MemberType == MemberTypes.Property)\r
+ targetValueType = b.Target.Property.PropertyType;\r
+ else if (b.Target.Member.MemberType == MemberTypes.Field)\r
+ targetValueType = b.Target.Field.FieldType;\r
else\r
throw new Exception ("unhandle target member type in binding");\r
}\r
\r
if (!targetValueType.IsValueType)\r
il.Emit(OpCodes.Castclass, targetValueType);\r
- else if (rb.Binding.Property.PropertyType != targetValueType)\r
- il.Emit(OpCodes.Callvirt, CompilerServices.GetConvertMethod( rb.Binding.Property.PropertyType ));\r
+ else if (b.Source.Property.PropertyType != targetValueType)\r
+ il.Emit(OpCodes.Callvirt, CompilerServices.GetConvertMethod( b.Source.Property.PropertyType ));\r
else\r
- il.Emit(OpCodes.Unbox_Any, rb.Binding.Property.PropertyType);\r
+ il.Emit(OpCodes.Unbox_Any, b.Source.Property.PropertyType);\r
\r
- il.Emit(OpCodes.Callvirt, rb.Binding.Property.GetSetMethod());\r
+ il.Emit(OpCodes.Callvirt, b.Source.Property.GetSetMethod());\r
il.Emit (OpCodes.Br, endMethod);\r
i++;\r
\r
\r
Delegate del = dm.CreateDelegate(ei.EventHandlerType, this);\r
MethodInfo addHandler = ei.GetAddMethod ();\r
- addHandler.Invoke(grouped [0].Target, new object[] {del});\r
+ addHandler.Invoke(grouped [0].Target.Instance, new object[] {del});\r
}\r
}\r
/// <summary>\r
Type sourceType = this.GetType();\r
\r
#region Retrieve EventHandler parameter type\r
- MethodInfo evtInvoke = binding.Event.EventHandlerType.GetMethod ("Invoke");\r
+ MethodInfo evtInvoke = binding.Source.Event.EventHandlerType.GetMethod ("Invoke");\r
ParameterInfo[] evtParams = evtInvoke.GetParameters ();\r
Type handlerArgsType = evtParams [1].ParameterType;\r
#endregion\r
\r
Type[] args = {typeof(object), typeof(object),handlerArgsType};\r
- DynamicMethod dm = new DynamicMethod("dynHandle",\r
+ DynamicMethod dm = new DynamicMethod(binding.NewDynMethodId,\r
typeof(void), \r
args,\r
sourceType);\r
string src = binding.Expression.Trim();\r
\r
if (! (src.StartsWith("{") || src.EndsWith ("}"))) \r
- throw new Exception (string.Format("GOML:Malformed {0} Event handler: {1}", binding.SourceMember.Name, binding.Expression));\r
+ throw new Exception (string.Format("GOML:Malformed {0} Event handler: {1}", binding.Source.Member.Name, binding.Expression));\r
\r
src = src.Substring (1, src.Length - 2);\r
string[] srcLines = src.Split (new char[] { ';' });\r
\r
#endregion\r
\r
- Delegate del = dm.CreateDelegate(binding.Event.EventHandlerType,this);\r
- MethodInfo addHandler = binding.Event.GetAddMethod ();\r
+ Delegate del = dm.CreateDelegate(binding.Source.Event.EventHandlerType,this);\r
+ MethodInfo addHandler = binding.Source.Event.GetAddMethod ();\r
addHandler.Invoke(this, new object[] {del});\r
}\r
\r
continue;\r
}\r
if (mi.MemberType == MemberTypes.Event) {\r
- this.Bindings.Add (new Binding (mi, attValue));\r
+ this.Bindings.Add (new Binding (new MemberReference(this, mi), attValue));\r
continue;\r
}\r
if (mi.MemberType == MemberTypes.Property) {\r
if (!attValue.EndsWith("}"))\r
throw new Exception (string.Format("GOML:Malformed binding: {0}", attValue));\r
\r
- this.Bindings.Add (new Binding (pi, attValue.Substring (1, attValue.Length - 2)));\r
+ this.Bindings.Add (new Binding (new MemberReference(this, pi), attValue.Substring (1, attValue.Length - 2)));\r
continue;\r
}\r
\r
/// and delete ref of this in Shared interface refs\r
/// </summary>\r
public virtual void ClearBinding(){\r
-// object ds = this.DataSource;\r
-// if (ds != null) {\r
-// Type dataSourceType = ds.GetType ();\r
-// EventInfo evtInfo = dataSourceType.GetEvent ("ValueChanged");\r
-// if (evtInfo != null) {\r
-// FieldInfo evtFi = CompilerServices.GetEventHandlerField (dataSourceType, "ValueChanged");\r
-// MulticastDelegate multicastDelegate = evtFi.GetValue (ds) as MulticastDelegate;\r
-// if (multicastDelegate != null) { \r
-// foreach (Delegate d in multicastDelegate.GetInvocationList()) {\r
-// string dn = d.Method.Name;\r
-// if (!dn.StartsWith ("dynHandle_"))\r
-// continue;\r
-// int did = int.Parse (dn.Substring (10));\r
-// if (this.DynamicMethodIds.Contains (did))\r
-// evtInfo.RemoveEventHandler (ds, d);\r
-// }\r
-// }\r
-// }\r
-// }\r
-// Interface.Unreference (this);\r
-\r
+ foreach (Binding b in Bindings) {\r
+ if (string.IsNullOrEmpty (b.DynMethodId))\r
+ continue;\r
+ Type dataSourceType = b.Target.Instance.GetType ();\r
+ EventInfo evtInfo = dataSourceType.GetEvent ("ValueChanged");\r
+ FieldInfo evtFi = CompilerServices.GetEventHandlerField (dataSourceType, "ValueChanged");\r
+ MulticastDelegate multicastDelegate = evtFi.GetValue (b.Target.Instance) as MulticastDelegate;\r
+ if (multicastDelegate != null) { \r
+ foreach (Delegate d in multicastDelegate.GetInvocationList()) { \r
+ if (d.Method.Name == b.DynMethodId)\r
+ evtInfo.RemoveEventHandler (b.Target.Instance, d);\r
+ }\r
+ }\r
+ }\r
}\r
}\r
}\r