Beispiel #1
0
        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);
                });
            }
        }