public static void ProcessWritableProperties(this ObjectHandlerRequest command, ICsharpExpressionDumperCallback callback, IEnumerable <PropertyInfo> properties) { callback.ChainAppendLine() .ChainAppend(new string(' ', command.Level * 4)) .ChainAppendLine("{"); var level = command.Level + 1; foreach (var property in properties) { var propertyValue = property.GetValue(command.Instance); var propertyType = propertyValue?.GetType(); callback.Append(new string(' ', level * 4)); var propertyCommand = new CustomTypeHandlerRequest(propertyValue, propertyType, level); var propertyIsCustom = callback.IsPropertyCustom(propertyCommand, $"{property.Name} = ", ","); if (!propertyIsCustom) { callback.ChainAppend(property.Name) .ChainAppend(" = ") .ChainProcessRecursive(propertyValue, propertyValue?.GetType(), level) .ChainAppend(","); } callback.AppendLine(); } level--; callback.ChainAppend(new string(' ', level * 4)) .ChainAppend("}"); }
private static void AppendFinalize(ObjectHandlerRequest command, ICsharpExpressionDumperCallback callback, int level, bool first, PropertyInfo[] properties, List <string> processedProperties) { var writableProperties = properties.Where ( property => (command.IsAnonymousType || !property.IsReadOnly()) && !processedProperties.Contains(property.Name) && callback.IsPropertyValid(command, property) ).ToArray(); if (!first) { callback.ChainAppend(new string(' ', level * 4)) .ChainAppend(")"); } else if (!command.IsAnonymousType && writableProperties.Length == 0) { callback.Append("()"); } if (writableProperties.Length > 0) { command.ProcessWritableProperties(callback, writableProperties); } }
public bool ProcessInstance(ObjectHandlerRequest command, ICsharpExpressionDumperCallback callback) { var type = command.Type ?? command.InstanceType; if (type == null) { return(false); } var level = command.Level + 1; var first = true; var properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance); var processedProperties = new List <string>(); foreach (var property in properties.Where(x => callback.IsPropertyValid(command, x))) { if (type.GetMethods().Any(x => x.Name == $"With{property.Name}")) { first = ProcessBuilderMethod(command, callback, level, first, processedProperties, property, "With"); } else if (type.GetMethods().Any(x => x.Name == $"Add{property.Name}")) { first = ProcessBuilderMethod(command, callback, level, first, processedProperties, property, "Add"); } } if (first) { // No 'With' or 'Add' methods found, let the default object handler handle this return(false); } return(true); }
public bool ProcessInstance(ObjectHandlerRequest command, ICsharpExpressionDumperCallback callback) { if (command.Instance == null) { return(false); } var type = command.Type ?? command.InstanceType; if (type == null) { return(false); } var level = command.Level + 1; var first = true; var ctor = callback.ResolveConstructor(type); var properties = type.GetProperties(BindingFlags.Public | BindingFlags.Instance); var processedProperties = new List <string>(); first = AppendReadOnlyProperties(command, callback, level, first, ctor, properties, processedProperties); level--; AppendFinalize(command, callback, level, first, properties, processedProperties); return(true); }
private static bool ProcessBuilderMethod(ObjectHandlerRequest command, ICsharpExpressionDumperCallback callback, int level, bool first, List <string> processedProperties, PropertyInfo property, string methodPrefix) { if (first) { callback.Append("()"); first = false; } var propertyValue = property.GetValue(command.Instance); var addedSomething = false; if (methodPrefix == "Add" && !(propertyValue is string) && propertyValue is IEnumerable enumerable) { var firstVal = true; level++; foreach (var value in enumerable.OfType <object>()) { if (firstVal) { firstVal = false; addedSomething = true; callback.ChainAppendLine() .ChainAppend(new string(' ', (level - 1) * 4)) .ChainAppend($".{methodPrefix}{property.Name}(") .ChainAppendLine() .ChainAppend(new string(' ', level * 4)); } else { callback.ChainAppend(",") .ChainAppendLine() .ChainAppend(new string(' ', level * 4)); } callback.ProcessRecursive(value, value?.GetType(), level); } } else { addedSomething = true; callback.ChainAppendLine() .ChainAppend(new string(' ', level * 4)) .ChainAppend($".{methodPrefix}{property.Name}(") .ChainProcessRecursive(propertyValue, propertyValue?.GetType(), level); } if (addedSomething) { callback.Append(")"); } processedProperties.Add(property.Name); return(first); }
public void ProcessInstance_Returns_True_When_PropertyValue_On_Immutable_Instance_Is_Null() { // Arrange var sut = new DefaultObjectHandler(); var instance = new MyImmutableClass("test"); var command = new ObjectHandlerRequest(instance, typeof(MyImmutableClass), 0, typeof(MyImmutableClass), false); var callbackMock = new Mock <ICsharpExpressionDumperCallback>(); // Act var actual = sut.ProcessInstance(command, callbackMock.Object); // Assert actual.Should().BeTrue(); }
public void ProcessInstance_Returns_False_On_Poco() { // Arrange var sut = new BuilderObjectHandler(); var instance = new MyPocoClass(); var command = new ObjectHandlerRequest(instance, typeof(MyPocoClass), 0, typeof(MyPocoClass), false); var callbackMock = new Mock <ICsharpExpressionDumperCallback>(); // Act var actual = sut.ProcessInstance(command, callbackMock.Object); // Assert actual.Should().BeFalse(); }
public void Can_Generate_Code_With_CustomObjectHandler() { // Arrange var sut = new BuilderObjectHandler(); var instance = new MyBuilder().WithName("Test").AddValues("1", "2", "3"); var command = new ObjectHandlerRequest(instance, typeof(MyBuilder), 0, typeof(MyBuilder), false); var callbackMock = new Mock <ICsharpExpressionDumperCallback>(); callbackMock.Setup(x => x.IsPropertyValid(It.IsAny <ObjectHandlerRequest>(), It.IsAny <PropertyInfo>())).Returns(true); // Act var actual = sut.ProcessInstance(command, callbackMock.Object); // Assert actual.Should().BeTrue(); }
public void ProcessInstance_Returns_False_On_Null_Type() { // Arrange var sut = new BuilderObjectHandler(); object?instance = null; var command = new ObjectHandlerRequest(instance, null, 0, null, false); var callbackMock = new Mock <ICsharpExpressionDumperCallback>(); callbackMock.Setup(x => x.IsPropertyValid(It.IsAny <ObjectHandlerRequest>(), It.IsAny <PropertyInfo>())).Returns(true); // Act var actual = sut.ProcessInstance(command, callbackMock.Object); // Assert actual.Should().BeFalse(); }
public bool IsValid(ObjectHandlerRequest command, PropertyInfo propertyInfo) { var defaultValue = propertyInfo.PropertyType.IsValueType && Nullable.GetUnderlyingType(propertyInfo.PropertyType) == null ? Activator.CreateInstance(propertyInfo.PropertyType) : null; var actualValue = propertyInfo.GetValue(command.Instance); if (defaultValue == null && actualValue == null) { return(false); } return(defaultValue == null || actualValue == null || !actualValue.Equals(defaultValue)); }
private static bool AppendReadOnlyProperties(ObjectHandlerRequest command, ICsharpExpressionDumperCallback callback, int level, bool first, ConstructorInfo?ctor, PropertyInfo[] properties, List <string> processedProperties) { if (!command.IsAnonymousType && ctor != null) { var arguments = ctor.GetParameters(); if (arguments.Length > 0) { foreach (var argument in arguments) { var readOnlyProperty = callback.ResolveReadOnlyProperty(properties, ctor, argument); if (readOnlyProperty == null) { continue; } first = AppendInitialization(callback, level, first); processedProperties.Add(readOnlyProperty.Name); var value = readOnlyProperty.GetValue(command.Instance); callback.ChainAppend(new string(' ', level * 4)) .ChainAppend(argument.Name) .ChainAppend(": ") .ChainProcessRecursive(value, value?.GetType(), level); } if (!first) { callback.AppendLine(); } } } return(first); }
private void DoProcessRecursive(object?instance, Type?type, StringBuilder builder, int level) { var instanceType = type ?? instance?.GetType(); var instanceRequest = new CustomTypeHandlerRequest(instance, instanceType, level); var instanceIsCustom = _customTypeHandlers.ProcessUntilSuccess(x => x.Process(instanceRequest, _instanceCallback)); if (!instanceIsCustom && instanceType != null) { var isAnonymousType = instanceType.IsAnonymousType(); _instanceCallback.Append("new "); if (!isAnonymousType) { _instanceCallback.AppendTypeName(instanceType); } var objectHandlerCommand = new ObjectHandlerRequest(instance, instanceType, level, type, isAnonymousType); var success = _objectHandlers.ProcessUntilSuccess(x => x.ProcessInstance(objectHandlerCommand, _instanceCallback)); if (!success) { throw new InvalidOperationException($"There is no object handler which supports object of type [{instanceType?.FullName}]"); } } }
public bool IsPropertyValid(ObjectHandlerRequest command, PropertyInfo propertyInfo) => _objectHandlerPropertyFilters.All(x => x.IsValid(command, propertyInfo));