protected static void SetStaticField(ICommonType frameworkElementType, string patchingFieldName) { FakeCommonTypeBuilder.GetMockFor(frameworkElementType.GetField(patchingFieldName, true).MonoCecil).Setup(field => field.IsStatic).Returns(true); }
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); } }
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); } }