private static void CheckViewModel(IHasType commandType, ICommonType viewModelType)
        {
            var errorsService = new ErrorsService();

            foreach (var method in viewModelType.Methods)
            {
                if (method.ContainsAttribute <PatchingCommandAttribute>())
                {
                    if (method.ParameterTypes.Any())
                    {
                        errorsService.AddError($"Patching method '{method.Name}' can not have parameters");
                    }

                    if (method.ContainsAttribute <NotPatchingCommandAttribute>())
                    {
                        errorsService.AddError($"Patching method '{method.Name}' can not have " +
                                               $"'{nameof(PatchingCommandAttribute)}' and '{nameof(NotPatchingCommandAttribute)}' at the same time");
                    }

                    if (method.ReturnType != typeof(void))
                    {
                        errorsService.AddError($"Patching method '{method.Name}' can not have " +
                                               $"'{method.ReturnType.FullName}' return type, allowable types: '{typeof(void).FullName}'");
                    }
                }

                foreach (var attribute in method.GetCastedAttributes <ConnectMethodToMethodAttribute>())
                {
                    if (method.ParameterTypes.Any())
                    {
                        errorsService.AddError($"Patching method '{method.Name}' can not have parameters");
                    }

                    if (method.ContainsAttribute <NotPatchingCommandAttribute>())
                    {
                        errorsService.AddError($"Patching method '{method.Name}' can not have '{nameof(NotPatchingCommandAttribute)}'");
                    }

                    if (method.ReturnType != typeof(void) && method.ReturnType != typeof(bool))
                    {
                        errorsService.AddError($"Patching method '{method.Name}' can not have " +
                                               $"'{method.ReturnType.FullName}' return type, allowable types: '{typeof(void).FullName}', '{typeof(bool).FullName}'");
                    }

                    var methods = viewModelType.GetMethods(attribute.ConnectingMethodName).ToArray();
                    switch (methods.Length)
                    {
                    case 0:
                        errorsService.AddError($"Not found method with name '{attribute.ConnectingMethodName}', " +
                                               $"specified in '{nameof(ConnectMethodToMethodAttribute)}' at method '{method.Name}'");
                        break;

                    case 1:
                        var singleMethod = methods.Single();

                        if (singleMethod.ParameterTypes.Any())
                        {
                            errorsService.AddError($"Patching method '{singleMethod.Name}' can not have parameters, " +
                                                   $"connection in '{nameof(ConnectMethodToMethodAttribute)}' at method '{method.Name}'");
                        }

                        if (singleMethod.ContainsAttribute <NotPatchingCommandAttribute>())
                        {
                            errorsService.AddError($"Patching method '{singleMethod.Name}' can not have '{nameof(NotPatchingCommandAttribute)}', " +
                                                   $"connection in '{nameof(ConnectMethodToMethodAttribute)}' at method '{method.Name}'");
                        }

                        if (singleMethod.ReturnType != typeof(void) && singleMethod.ReturnType != typeof(bool))
                        {
                            errorsService.AddError($"Patching method '{singleMethod.Name}' can not have " +
                                                   $"'{singleMethod.ReturnType.FullName}' return type, allowable types: '{typeof(void).FullName}', '{typeof(bool).FullName}', " +
                                                   $"connection in '{nameof(ConnectMethodToMethodAttribute)}' at method '{method.Name}'");
                        }
                        else
                        {
                            if (method.ReturnType == typeof(void) && singleMethod.ReturnType == typeof(void))
                            {
                                errorsService.AddError($"Can not be connect two execute methods: '{method.Name}' and '{singleMethod.Name}', " +
                                                       $"connection in '{nameof(ConnectMethodToMethodAttribute)}' at method '{method.Name}'");
                            }

                            if (method.ReturnType == typeof(bool) && singleMethod.ReturnType == typeof(bool))
                            {
                                errorsService.AddError($"Can not be connect two can execute methods: '{method.Name}' and '{singleMethod.Name}', " +
                                                       $"connection in '{nameof(ConnectMethodToMethodAttribute)}' at method '{method.Name}'");
                            }
                        }

                        break;

                    default:
                        errorsService.AddError($"Found several methods with name '{attribute.ConnectingMethodName}', " +
                                               $"specified in '{nameof(ConnectMethodToMethodAttribute)}' at method '{method.Name}'");
                        break;
                    }
                }

                foreach (var attribute in method.GetCastedAttributes <ConnectMethodToPropertyAttribute>())
                {
                    if (method.ParameterTypes.Any())
                    {
                        errorsService.AddError($"Patching method '{method.Name}' can not have parameters");
                    }

                    if (method.ContainsAttribute <NotPatchingCommandAttribute>())
                    {
                        errorsService.AddError($"Patching method '{method.Name}' can not have '{nameof(NotPatchingCommandAttribute)}'");
                    }

                    if (method.ReturnType != typeof(void))
                    {
                        errorsService.AddError($"Patching method '{method.Name}' can not have " +
                                               $"'{method.ReturnType.FullName}' return type, allowable types: '{typeof(void).FullName}'");
                    }

                    var property = viewModelType.GetProperty(attribute.ConnectingPropertyName);

                    if (property == null)
                    {
                        errorsService.AddError($"Not found property with name '{attribute.ConnectingPropertyName}', " +
                                               $"specified in '{nameof(ConnectMethodToPropertyAttribute)}' at method '{method.Name}'");
                    }
                    else if (property.IsNotInheritedFrom(commandType))
                    {
                        errorsService.AddError($"Property '{property.Name}' can not have '{property.Type.FullName}' type, " +
                                               $"allowable types: all inherited from '{KnownTypeNames.ICommand}', " +
                                               $"connection in '{nameof(ConnectMethodToPropertyAttribute)}' at method '{method.Name}'");
                    }
                }
            }

            foreach (var property in viewModelType.Properties)
            {
                if (property.IsInheritedFrom(commandType))
                {
                    foreach (var attribute in property.GetCastedAttributes <ConnectPropertyToFieldAttribute>())
                    {
                        var field = viewModelType.GetField(attribute.ConnectingFieldName);

                        if (field == null)
                        {
                            errorsService.AddError($"Not found field with name '{attribute.ConnectingFieldName}', " +
                                                   $"specified in '{nameof(ConnectPropertyToFieldAttribute)}' at property '{property.Name}'");
                        }
                        else if (property.IsNot(field))
                        {
                            errorsService.AddError($"Types do not match between property '{property.Name}' and field '{field.Name}', " +
                                                   $"connection in '{nameof(ConnectPropertyToFieldAttribute)}' at property '{property.Name}'");
                        }
                    }
                }

                var connectPropertyToMethodAttributes = property.GetCastedAttributes <ConnectPropertyToMethodAttribute>().ToArray();
                if (!connectPropertyToMethodAttributes.Any())
                {
                    continue;
                }

                if (property.IsNotInheritedFrom(commandType))
                {
                    errorsService.AddError($"Patching property '{property.Name}' can not have '{property.Type.FullName}' type, " +
                                           $"allowable types: all inherited from '{KnownTypeNames.ICommand}'");
                }

                foreach (var namesToMethods in connectPropertyToMethodAttributes.Select(attribute => attribute.ConnectingMethodNames.Select(name => new { Name = name, Methods = viewModelType.GetMethods(name).ToArray() }).ToArray()))
                {
                    foreach (var nameToMethods in namesToMethods)
                    {
                        switch (nameToMethods.Methods.Length)
                        {
                        case 0:
                            errorsService.AddError($"Not found method with name '{nameToMethods.Name}', " +
                                                   $"specified in '{nameof(ConnectPropertyToMethodAttribute)}' at property '{property.Name}'");
                            break;

                        case 1:
                            var singleMethod = nameToMethods.Methods.Single();

                            if (singleMethod.ParameterTypes.Any())
                            {
                                errorsService.AddError($"Patching method '{singleMethod.Name}' can not have parameters, " +
                                                       $"connection in '{nameof(ConnectPropertyToMethodAttribute)}' at property '{property.Name}'");
                            }

                            if (singleMethod.ContainsAttribute <NotPatchingCommandAttribute>())
                            {
                                errorsService.AddError($"Patching method '{singleMethod.Name}' can not have '{nameof(NotPatchingCommandAttribute)}', " +
                                                       $"connection in '{nameof(ConnectPropertyToMethodAttribute)}' at property '{property.Name}'");
                            }

                            if (singleMethod.ReturnType != typeof(void) && singleMethod.ReturnType != typeof(bool))
                            {
                                errorsService.AddError($"Patching method '{singleMethod.Name}' can not have " +
                                                       $"'{singleMethod.ReturnType.FullName}' return type, allowable types: '{typeof(void).FullName}', '{typeof(bool).FullName}', " +
                                                       $"connection in '{nameof(ConnectPropertyToMethodAttribute)}' at property '{property.Name}'");
                            }
                            break;

                        default:
                            errorsService.AddError($"Found several methods with name '{nameToMethods.Name}', " +
                                                   $"specified in '{nameof(ConnectPropertyToMethodAttribute)}' at property '{property.Name}'");
                            break;
                        }
                    }

                    switch (namesToMethods.Length)
                    {
                    case 1:
                        var singleNameToMethods = namesToMethods.Single();

                        if (singleNameToMethods.Methods.Length == 1 && singleNameToMethods.Methods.Single().ReturnType == typeof(bool))
                        {
                            errorsService.AddError($"Can not be connect to can execute method '{singleNameToMethods.Methods.Single().Name}', " +
                                                   $"connection in '{nameof(ConnectPropertyToMethodAttribute)}' at property '{property.Name}'");
                        }
                        break;

                    case 2:
                        if (namesToMethods[0].Methods.Length == 1 && namesToMethods[1].Methods.Length == 1)
                        {
                            var singleFirstMethod  = namesToMethods[0].Methods.Single();
                            var singleSecondMethod = namesToMethods[1].Methods.Single();

                            if (singleFirstMethod.ReturnType == typeof(void) && singleSecondMethod.ReturnType == typeof(void))
                            {
                                errorsService.AddError($"Can not be connect to two execute methods: '{singleFirstMethod.Name}' and '{singleSecondMethod.Name}', " +
                                                       $"connection in '{nameof(ConnectPropertyToMethodAttribute)}' at property '{property.Name}'");
                            }

                            if (singleFirstMethod.ReturnType == typeof(bool) && singleSecondMethod.ReturnType == typeof(bool))
                            {
                                errorsService.AddError($"Can not be connect to two can execute methods: '{singleFirstMethod.Name}' and '{singleSecondMethod.Name}', " +
                                                       $"connection in '{nameof(ConnectPropertyToMethodAttribute)}' at property '{property.Name}'");
                            }
                        }

                        break;
                    }
                }
            }

            foreach (var field in viewModelType.Fields.Where(field => field.IsInheritedFrom(commandType)))
            {
                foreach (var attribute in field.GetCastedAttributes <ConnectFieldToPropertyAttribute>())
                {
                    var property = viewModelType.GetProperty(attribute.ConnectingPropertyName);

                    if (property == null)
                    {
                        errorsService.AddError($"Not found property with name '{attribute.ConnectingPropertyName}', " +
                                               $"specified in '{nameof(ConnectFieldToPropertyAttribute)}' at field '{field.Name}'");
                    }
                    else if (field.IsNot(property))
                    {
                        errorsService.AddError($"Types do not match between field '{field.Name}' and property '{property.Name}', " +
                                               $"connection in '{nameof(ConnectFieldToPropertyAttribute)}' at field '{field.Name}'");
                    }
                }
            }

            if (errorsService.HasErrors)
            {
                throw new ViewModelCommandPatchingException(errorsService);
            }
        }
예제 #2
0
        private static void CheckViewModel(IHasType commandType, ICommonType viewModelType)
        {
            var errorsService = new ErrorsService();

            foreach (var property in viewModelType.Properties.Select(property => property))
            {
                var patchingPropertyAttribute = property.GetCastedAttribute <PatchingPropertyAttribute>();
                if (patchingPropertyAttribute != null)
                {
                    if (property.IsInheritedFrom(commandType))
                    {
                        errorsService.AddError($"Patching property '{property.Name}' can not inherited from '{KnownTypeNames.ICommand}'");
                    }

                    if (property.ContainsAttribute <NotPatchingPropertyAttribute>())
                    {
                        errorsService.AddError($"Patching property '{property.Name}' can not have " +
                                               $"'{nameof(PatchingPropertyAttribute)}' and '{nameof(NotPatchingPropertyAttribute)}' at the same time");
                    }

                    CheckCalledMethod(errorsService, viewModelType, patchingPropertyAttribute.CalledMethodNameBeforeGetProperty, property.Name);
                    CheckCalledMethod(errorsService, viewModelType, patchingPropertyAttribute.CalledMethodNameBeforeSetProperty, property.Name);
                    CheckCalledMethod(errorsService, viewModelType, patchingPropertyAttribute.CalledMethodNameAfterSuccessSetProperty, property.Name);
                    CheckCalledMethod(errorsService, viewModelType, patchingPropertyAttribute.CalledMethodNameAfterSetProperty, property.Name);
                }

                if (property.IsInheritedFrom(commandType))
                {
                    continue;
                }

                var connectPropertyToFieldAttributes = property.GetCastedAttributes <ConnectPropertyToFieldAttribute>().ToArray();
                if (!connectPropertyToFieldAttributes.Any())
                {
                    continue;
                }

                if (property.ContainsAttribute <NotPatchingPropertyAttribute>())
                {
                    errorsService.AddError($"Patching property '{property.Name}' can not have '{nameof(NotPatchingPropertyAttribute)}', " +
                                           $"connection in '{nameof(ConnectPropertyToFieldAttribute)}' at property '{property.Name}'");
                }

                foreach (var attribute in connectPropertyToFieldAttributes)
                {
                    var field = viewModelType.GetField(attribute.ConnectingFieldName);

                    if (field == null)
                    {
                        errorsService.AddError($"Not found field with name '{attribute.ConnectingFieldName}', " +
                                               $"specified in '{nameof(ConnectPropertyToFieldAttribute)}' at property '{property.Name}'");
                    }
                    else if (property.IsNot(field))
                    {
                        errorsService.AddError($"Types do not match between property '{property.Name}' and field '{field.Name}', " +
                                               $"connection in '{nameof(ConnectPropertyToFieldAttribute)}' at property '{property.Name}'");
                    }
                }
            }

            foreach (var field in viewModelType.Fields.Select(field => field).Where(field => field.IsNotInheritedFrom(commandType)))
            {
                foreach (var attribute in field.GetCastedAttributes <ConnectFieldToPropertyAttribute>())
                {
                    var property = viewModelType.GetProperty(attribute.ConnectingPropertyName);

                    if (property == null)
                    {
                        errorsService.AddError($"Not found property with name '{attribute.ConnectingPropertyName}', " +
                                               $"specified in '{nameof(ConnectFieldToPropertyAttribute)}' at field '{field.Name}'");
                    }
                    else
                    {
                        if (field.IsNot(property))
                        {
                            errorsService.AddError($"Types do not match between field '{field.Name}' and property '{property.Name}', " +
                                                   $"connection in '{nameof(ConnectFieldToPropertyAttribute)}' at field '{field.Name}'");
                        }

                        if (property.ContainsAttribute <NotPatchingPropertyAttribute>())
                        {
                            errorsService.AddError($"Patching property '{property.Name}' can not have '{nameof(NotPatchingPropertyAttribute)}', " +
                                                   $"connection in '{nameof(ConnectFieldToPropertyAttribute)}' at field '{field.Name}'");
                        }
                    }
                }
            }

            if (errorsService.HasErrors)
            {
                throw new ViewModelPropertyPatchingException(errorsService);
            }
        }
        private static void CheckFrameworkElement(ICommonType frameworkElementType, ICommonType dependencyPropertyType)
        {
            var errorsService = new ErrorsService();

            foreach (var property in frameworkElementType.Properties)
            {
                if (property.ContainsAttribute <PatchingPropertyAttribute>() && property.ContainsAttribute <NotPatchingPropertyAttribute>())
                {
                    errorsService.AddError($"Patching property '{property.Name}' can not have " +
                                           $"'{nameof(PatchingPropertyAttribute)}' and '{nameof(NotPatchingPropertyAttribute)}' at the same time");
                }

                var connectPropertyToDependencyAttributes = property.GetCastedAttributes <ConnectPropertyToFieldAttribute>().ToArray();
                if (!connectPropertyToDependencyAttributes.Any())
                {
                    continue;
                }

                if (property.ContainsAttribute <NotPatchingPropertyAttribute>())
                {
                    errorsService.AddError($"Patching property '{property.Name}' can not have '{nameof(NotPatchingPropertyAttribute)}', " +
                                           $"connection in '{nameof(ConnectPropertyToFieldAttribute)}' at property '{property.Name}'");
                }

                foreach (var attribute in connectPropertyToDependencyAttributes)
                {
                    var field = frameworkElementType.GetField(attribute.ConnectingFieldName);

                    if (field == null)
                    {
                        errorsService.AddError($"Not found field with name '{attribute.ConnectingFieldName}', " +
                                               $"specified in '{nameof(ConnectPropertyToFieldAttribute)}' at property '{property.Name}'");
                    }
                    else
                    {
                        if (!field.MonoCecil.IsStatic)
                        {
                            errorsService.AddError($"Patching field '{field.Name}' can not be non static, " +
                                                   $"connection in '{nameof(ConnectPropertyToFieldAttribute)}' at property '{property.Name}'");
                        }

                        if (field.IsNot(dependencyPropertyType))
                        {
                            errorsService.AddError($"Patching field '{field.Name}' can not have " +
                                                   $"'{field.Type.FullName}' type, allowable types: '{dependencyPropertyType.FullName}', " +
                                                   $"connection in '{nameof(ConnectPropertyToFieldAttribute)}' at property '{property.Name}'");
                        }
                    }
                }
            }

            foreach (var field in frameworkElementType.Fields)
            {
                var connectDependencyToPropertyAttributes = field.GetCastedAttributes <ConnectFieldToPropertyAttribute>().ToArray();
                if (!connectDependencyToPropertyAttributes.Any())
                {
                    continue;
                }

                if (field.IsNot(dependencyPropertyType))
                {
                    errorsService.AddError($"Patching field '{field.Name}' can not have " +
                                           $"'{field.Type.FullName}' type, allowable types: '{dependencyPropertyType.FullName}', " +
                                           $"connection in '{nameof(ConnectFieldToPropertyAttribute)}' at field '{field.Name}'");
                }

                foreach (var attribute in connectDependencyToPropertyAttributes)
                {
                    var property = frameworkElementType.GetProperty(attribute.ConnectingPropertyName);

                    if (property == null)
                    {
                        errorsService.AddError($"Not found property with name '{attribute.ConnectingPropertyName}', " +
                                               $"specified in '{nameof(ConnectFieldToPropertyAttribute)}' at field '{field.Name}'");
                    }
                    else if (property.ContainsAttribute <NotPatchingPropertyAttribute>())
                    {
                        errorsService.AddError($"Patching property '{property.Name}' can not have '{nameof(NotPatchingPropertyAttribute)}', " +
                                               $"connection in '{nameof(ConnectFieldToPropertyAttribute)}' at field '{field.Name}'");
                    }
                }
            }

            if (errorsService.HasErrors)
            {
                throw new FrameworkElementDependencyPatchingException(errorsService);
            }
        }