예제 #1
0
        /// <summary>
        /// If a view model's property is a delegate, wrap the action in a Command object and invoke it.
        /// </summary>
        /// <param name="viewModel">View model object.</param>
        /// <param name="propInfo">Delegate property type info.</param>
        /// <param name="newValue">Delegate argument.</param>
        /// <returns>Whether the delegate was invoked.</returns>
        private bool InvokeDelegate(object viewModel, PropertyInfoHelper propInfo, string newValue)
        {
            var propType = propInfo.PropertyType.GetTypeInfo();
            var argTypes = propType.GetGenericArguments();

            Type delegateReturnType = propType.GetMethod(nameof(Action.Invoke)).ReturnType;

            if (delegateReturnType == typeof(void))
            {
                var cmdType = argTypes.Length > 0 ? typeof(Command <>).MakeGenericType(argTypes) : typeof(Command);
                (Activator.CreateInstance(cmdType, new object[] { propInfo.GetValue(viewModel) }) as ICommand)?.Execute(newValue);
                return(true);
            }
            else if (delegateReturnType == typeof(Task))
            {
                var cmdType = argTypes.Length > 1 ? typeof(Command <>).MakeGenericType(argTypes[0]) : typeof(Command);
                var task    = (Activator.CreateInstance(cmdType, new object[] { propInfo.GetValue(viewModel) }) as IAsyncCommand)?.ExecuteAsync(newValue);
                if (viewModel is BaseVM)
                {
                    (viewModel as BaseVM).AsyncCommands.Add(task);
                }
                return(true);
            }

            return(false);
        }
예제 #2
0
        /// <summary>
        /// Deserializes a property value of a view model.
        /// </summary>
        /// <param name="viewModel">View model to deserialize the property to.</param>
        /// <param name="vmPath">View model property path.</param>
        /// <param name="newValue">New value.</param>
        /// <returns>True if the value was deserialized.</returns>
        public bool Deserialize(object viewModel, string vmPath, string newValue)
        {
            try
            {
                var vmType = viewModel.GetType();
                var path   = vmPath.Split('.');
                for (int i = 0; i < path.Length; i++)
                {
                    var propName = path[i];
                    var propInfo = viewModel != null?PropertyInfoHelper.Find(viewModel, propName) : null;

                    if (propInfo == null)
                    {
                        return(false);
                    }

                    var propType = propInfo.PropertyType.GetTypeInfo();

                    if (i < path.Length - 1)
                    {
                        // Path that starts with $ sign means it is a key to an IEnumerable property.
                        // By convention we expect a method whose name is in this format:
                        // <IEnumerable property name>_get (for example: ListContent_get)
                        // to get the object whose key matches the given value in the path.
                        if (path[i + 1].StartsWith("$"))
                        {
                            var key        = path[i + 1].TrimStart('$');
                            var methodInfo = vmType.GetTypeInfo().GetMethod(propName + "_get");
                            if (methodInfo == null)
                            {
                                return(false);
                            }

                            viewModel = methodInfo.Invoke(viewModel, new object[] { key });
                            if (viewModel == null)
                            {
                                return(false);
                            }

                            vmType = viewModel.GetType();
                            i++;
                        }
                        else
                        {
                            viewModel = propInfo.GetValue(viewModel);
                            vmType    = viewModel?.GetType() ?? propInfo.PropertyType;
                        }
                    }
                    else if (viewModel == null)
                    {
                        return(false);
                    }
                    else if (typeof(ICommand).GetTypeInfo().IsAssignableFrom(propInfo.PropertyType))
                    {
                        // If the property type is ICommand, execute the command.
                        (propInfo.GetValue(viewModel) as ICommand)?.Execute(newValue);
                    }
                    else if (propType.IsSubclassOf(typeof(MulticastDelegate)) && propType.GetMethod(nameof(Action.Invoke)).ReturnType == typeof(void))
                    {
                        // If the property type is Action, wrap the action in a Command object and execute it.
                        var argTypes = propType.GetGenericArguments();
                        var cmdType  = argTypes.Length > 0 ? typeof(Command <>).MakeGenericType(argTypes) : typeof(Command);
                        (Activator.CreateInstance(cmdType, new object[] { propInfo.GetValue(viewModel) }) as ICommand)?.Execute(newValue);
                    }
                    else if (typeof(IReactiveProperty).GetTypeInfo().IsAssignableFrom(propInfo.PropertyType))
                    {
                        // If the property type is ReactiveProperty, set the new value into the object.
                        var reactiveProp = propInfo.GetValue(viewModel) as IReactiveProperty;
                        reactiveProp.Value = ConvertFromString(reactiveProp.PropertyType, newValue);
                    }
                    else if (propInfo.SetMethod != null)
                    {
                        // Update the new value to the property.
                        propInfo.SetValue(viewModel, ConvertFromString(propInfo.PropertyType, newValue));
                    }
                }
            }
            catch (Exception ex)
            {
                Trace.Fail(ex.ToString());
                throw ex;
            }

            return(true);
        }
예제 #3
0
        /// <summary>
        /// Deserializes a property value of a view model.
        /// </summary>
        /// <param name="viewModel">View model to deserialize the property to.</param>
        /// <param name="vmPath">View model property path.</param>
        /// <param name="newValue">New value.</param>
        /// <returns>True if the value was deserialized.</returns>
        public bool Deserialize(object viewModel, string vmPath, string newValue)
        {
            try
            {
                var vmType = viewModel.GetType();
                var path   = vmPath.Split('.');
                for (int i = 0; i < path.Length; i++)
                {
                    var propName = path[i];
                    var propInfo = viewModel != null?PropertyInfoHelper.Find(viewModel, propName) : null;

                    if (propInfo == null)
                    {
                        // If not a property, maybe it's a method with 0 or 1 argument.
                        if (InvokeIfMethod(viewModel, propName, newValue))
                        {
                            continue;
                        }
                        else
                        {
                            return(false);
                        }
                    }

                    var propType = propInfo.PropertyType.GetTypeInfo();

                    if (i < path.Length - 1)
                    {
                        // Path that starts with $ sign means it is a key to an IEnumerable property.
                        // By convention we expect a method whose name is in this format:
                        // <IEnumerable property name>_get (for example: ListContent_get)
                        // to get the object whose key matches the given value in the path.
                        if (path[i + 1].StartsWith("$"))
                        {
                            var key        = path[i + 1].TrimStart('$');
                            var methodInfo = vmType.GetTypeInfo().GetMethod(propName + "_get");
                            if (methodInfo == null)
                            {
                                return(false);
                            }

                            viewModel = methodInfo.Invoke(viewModel, new object[] { key });
                            if (viewModel == null)
                            {
                                return(false);
                            }

                            vmType = viewModel.GetType();
                            i++;
                        }
                        else
                        {
                            viewModel = propInfo.GetValue(viewModel);
                            vmType    = viewModel?.GetType() ?? propInfo.PropertyType;
                        }
                    }
                    else if (viewModel == null)
                    {
                        return(false);
                    }
                    else if (typeof(ICommand).GetTypeInfo().IsAssignableFrom(propInfo.PropertyType))
                    {
                        // If the property type is ICommand, execute the command.
                        (propInfo.GetValue(viewModel) as ICommand)?.Execute(newValue);
                    }
                    else if (propType.IsSubclassOf(typeof(MulticastDelegate)))
                    {
                        // If the property type is a delegate, wrap the action in a Command object and invoke it.
                        InvokeDelegate(viewModel, propInfo, newValue);
                    }
                    else if (typeof(IReactiveProperty).GetTypeInfo().IsAssignableFrom(propInfo.PropertyType))
                    {
                        // If the property type is ReactiveProperty, set the new value into the object.
                        var reactiveProp = propInfo.GetValue(viewModel) as IReactiveProperty;
                        reactiveProp.Value = ConvertFromString(reactiveProp.PropertyType, newValue);
                    }
                    else if (propInfo.SetMethod != null)
                    {
                        // Update the new value to the property.
                        propInfo.SetValue(viewModel, ConvertFromString(propInfo.PropertyType, newValue));
                    }
                }
            }
            catch (Exception ex)
            {
                Logger.LogError($"Failed to deserialize view model property '{vmPath}': {ex.Message}");
                throw ex;
            }

            return(true);
        }