private void Validate() { var del = _delegate as Delegate; if (TargetNode == null || TargetNode.DataContext == null) { _delegate = Empty; } else if (del == null || !ReferenceEquals(del.Target, TargetNode.DataContext)) { var targetObj = TargetNode.DataContext; var targetType = targetObj.GetType(); var targetMethod = targetType.GetMethod(MethodName, System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Static ); if (targetMethod == null) { Console.WriteLine("[JankyMethod] Method '{0}' does not exist on '{1}' or is not public", MethodName, targetType.FullName ); _delegate = Empty; return; } try { _delegate = (targetMethod.IsStatic) ? DynamicUtils.MakeCompatibleDelegate <TDelegate>(targetMethod) : DynamicUtils.MakeCompatibleDelegate <TDelegate>(targetMethod, targetObj); } catch { Console.WriteLine("[JankyMethod] Target Method '{0}' is not Compatible with '{1}'", targetType + "." + targetMethod.Name, typeof(TDelegate).ToString() ); _delegate = Empty; return; } } }
private Action <Node, string> MakeJankyPropertySetter(string targetProp) { var prop = Properties.First(x => x.Name.Equals(targetProp, StringComparison.OrdinalIgnoreCase)); const BindingFlags flags = BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance; var member_info = NodeType.GetMember(prop.Target, flags).First(); MethodInfo setterMethod; switch (member_info) { case PropertyInfo prop_info: setterMethod = prop_info.GetSetMethod(true); if (setterMethod == null) { throw new Exception("Property Has no Setter: " + prop_info.Name); } break; case MethodInfo method_info: setterMethod = method_info; if (method_info.GetParameters().Length != 1) { throw new Exception("Invalid Method Signature. Method must have one argument."); } break; case FieldInfo field_info: DynamicUtils.MakeFieldGetterSetter(field_info, out _, out setterMethod); break; default: throw new Exception("Member is not Supported"); } var setterDelegate = DynamicUtils.MakeCompatibleDelegate <Action <Node, object> >(setterMethod); var propertyType = setterMethod.GetParameters().Last().ParameterType; if (propertyType.IsSubclassOfRawGeneric(typeof(JankyProperty <>))) { var __wrapper__ = propertyType; var __dataType__ = __wrapper__.GetGenericArguments()[0]; var __converter__ = TypeDescriptor.GetConverter(__dataType__); if (!prop.DefaultValue.TryConvertTo(__dataType__, out var __defaultValue__)) { Console.WriteLine("Invalid Default Value for Property {0} in {1}", prop.Name, NodeType); } return((node, sourceValue) => { bool escapedSpecialName = false; if (sourceValue?.StartsWith("@@") == true || sourceValue?.StartsWith("##") == true) { sourceValue = sourceValue.Substring(1); escapedSpecialName = true; } object targetValue; // No Value Provided if (sourceValue == null) { targetValue = Activator.CreateInstance(__wrapper__, __defaultValue__); } // Method Binding else if (!escapedSpecialName && sourceValue.StartsWith("@")) { // Strip @ Sign var memberName = sourceValue.Substring(1); targetValue = Activator.CreateInstance(__wrapper__, node, memberName, __defaultValue__); } // Static Resource else if (!escapedSpecialName && sourceValue.StartsWith("#")) { var resourceKey = sourceValue.Substring(1); // Key not Present if (!node.Context.Resources.TryGetValue(resourceKey, out var resource)) { Console.WriteLine("Resource Key not Found: {0}", resourceKey); targetValue = Activator.CreateInstance(__wrapper__, __defaultValue__); } else { // Resource is EXPLICITLY set to null if (resource == null && __dataType__.IsValueType) { resource = Activator.CreateInstance(__dataType__); } // Resource is string, but target type isnt, Try Converting else if (resource.GetType() == typeof(string) && __dataType__ != typeof(string) && !((string)resource).TryConvertTo(__dataType__, out resource)) { Console.WriteLine("Can't convert Resource String {0} to Target Type {1}", resourceKey, __dataType__); resource = __defaultValue__; } //Else Resource is (probably) same type as target targetValue = Activator.CreateInstance(__wrapper__, resource); } } else { // Direct Set if (__dataType__ == typeof(string)) { targetValue = Activator.CreateInstance(__wrapper__, sourceValue); } // Convert and Set else { if (!sourceValue.TryConvertTo(__dataType__, out var converted)) { Console.WriteLine("Can't convert String '{0}' to Target Type '{1}'", sourceValue, __dataType__); converted = __defaultValue__; } targetValue = Activator.CreateInstance(__wrapper__, converted); } } setterDelegate(node, targetValue); }); } else if (propertyType.IsSubclassOfRawGeneric(typeof(JankyMethod <>))) { return((node, value) => { object instance; if (value.IsNullOrWhiteSpace()) { instance = Activator.CreateInstance(propertyType); } else if (!value.StartsWith("@") || value.StartsWith("@@")) { instance = Activator.CreateInstance(propertyType); #if DEBUG throw new NotSupportedException("Method Bindings can't be static values"); #else Console.WriteLine("Method Bindings can't be static values"); #endif } else { value = value.Substring(1); instance = Activator.CreateInstance(propertyType, node, value); } //propType.GetMethod("Validate", BindingFlags.Instance | BindingFlags.NonPublic).Invoke(instance, null); setterDelegate(node, instance); }); } else { var __dataType__ = propertyType; var __converter__ = TypeDescriptor.GetConverter(__dataType__); if (!prop.DefaultValue.TryConvertTo(__dataType__, out var __defaultValue__)) { Console.WriteLine("Invalid Default Value for Property {0} in {1}", prop.Name, NodeType); } var converter = TypeDescriptor.GetConverter(propertyType); return((node, sourceValue) => { bool escapedSpecialName = false; if (sourceValue?.StartsWith("@@") == true || sourceValue?.StartsWith("##") == true) { sourceValue = sourceValue.Substring(1); escapedSpecialName = true; } object targetValue; // No Value Provided if (sourceValue.IsNullOrWhiteSpace()) { targetValue = __defaultValue__; } else if (!escapedSpecialName && sourceValue.StartsWith("@")) { Console.WriteLine("Normal Properties don't support Binding"); targetValue = __defaultValue__; } else if (!escapedSpecialName && sourceValue.StartsWith("#")) { var resourceKey = sourceValue.Substring(1); // Key not Present if (!node.Context.Resources.TryGetValue(resourceKey, out var resource)) { Console.WriteLine("Resource Key not Found: {0}", resourceKey); targetValue = __defaultValue__; } else { // Resource is EXPLICITLY set to null if (resource == null && __dataType__.IsValueType) { resource = Activator.CreateInstance(__dataType__); } // Resource is string, but target type isnt, Try Converting else if (resource.GetType() == typeof(string) && __dataType__ != typeof(string) && !((string)resource).TryConvertTo(__dataType__, out resource)) { Console.WriteLine("Can't convert Resource String {0} to Target Type {1}", resourceKey, __dataType__); resource = __defaultValue__; } //Else Resource is (probably) same type as target targetValue = resource; } } else { // Direct Set if (__dataType__ == typeof(string)) { targetValue = sourceValue; } // Convert and Set else { if (!sourceValue.TryConvertTo(__dataType__, out var converted)) { Console.WriteLine("Can't convert String '{0}' to Target Type '{1}'", sourceValue, __dataType__); converted = __defaultValue__; } targetValue = converted; } } setterDelegate(node, targetValue); }); } }