using System;
using System.Reflection.Emit;
using System.Reflection;
using System.Collections;
using System.Diagnostics;
using System.Linq;
using System.Collections.Generic;
using System.Runtime.CompilerServices;
namespace go
{
public class MemberReference
{
public object Instance;
public MemberInfo Member;
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 MemberReference(){
}
public MemberReference(object _instance, MemberInfo _member = null)
{
Instance = _instance;
Member = _member;
}
public bool FindMember(string _memberName)
{
if (Instance == null)
return false;
Type t = Instance.GetType ();
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();
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 MemberReference Source;
public MemberReference Target;
public string Expression;
#region CTOR
public Binding(){}
public Binding(MemberReference _source, string _expression)
{
Source = _source;
Expression = _expression;
}
#endregion
public bool FindTarget(){
string member = null;
//if binding exp = '{}' => binding is done on datasource
if (string.IsNullOrEmpty (Expression)) {
Target = new MemberReference ((Source.Instance as GraphicObject).DataSource);
return true;
}
string[] bindingExp = Expression.Split ('/');
if (bindingExp.Length == 1) {
//datasource binding
Target = new MemberReference((Source.Instance as GraphicObject).DataSource);
member = bindingExp [0];
} else {
int ptr = 0;
ILayoutable tmp = Source.Instance as ILayoutable;
if (string.IsNullOrEmpty (bindingExp [0])) {
//if exp start with '/' => Graphic tree parsing start at top container
tmp = tmp.TopContainer as ILayoutable;
ptr++;
}
while (ptr < bindingExp.Length - 1) {
if (tmp == null)
return false;
if (bindingExp [ptr] == "..")
tmp = tmp.Parent as ILayoutable;
else if (bindingExp [ptr] == ".") {
if (ptr > 0)
throw new Exception ("Syntax error in binding, './' may only appear in first position");
tmp = Source.Instance as ILayoutable;
}else
tmp = (tmp as GraphicObject).FindByName (bindingExp [ptr]);
ptr++;
}
if (tmp == null)
return false;
string[] bindTrg = bindingExp [ptr].Split ('.');
if (bindTrg.Length == 1)
member = bindTrg [0];
else if (bindTrg.Length == 2){
tmp = (tmp as GraphicObject).FindByName (bindTrg [0]);
member = bindTrg [1];
} else
throw new Exception ("Syntax error in binding, expected 'go dot member'");
Target = new MemberReference(tmp);
}
if (Target == null) {
Debug.WriteLine ("Binding Source is null: " + Expression);
return false;
}
if (Target.FindMember (member))
return true;
Debug.WriteLine ("Binding member not found: " + member);
return false;
}
public void Reset()
{
Target = null;
dynMethodId = "";
}
}
public static class CompilerServices
{
static int dynHandleCpt = 0;
#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 (string ) )
return typeof(object).GetMethod("ToString", Type.EmptyTypes);
else
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
public 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;
}
///
/// Gets extension methods defined in assembley for extendedType
///
/// Extension methods enumerable
/// Assembly
/// Extended type to search for
public static IEnumerable GetExtensionMethods(Assembly assembly,
Type extendedType)
{
IEnumerable 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;
}
}
}