diff --git a/AgileMapper.UnitTests.MoreTestClasses.Vb/PublicNamedIndex.vb b/AgileMapper.UnitTests.MoreTestClasses.Vb/PublicNamedIndex.vb index 2482b16a..0944bc6b 100644 --- a/AgileMapper.UnitTests.MoreTestClasses.Vb/PublicNamedIndex.vb +++ b/AgileMapper.UnitTests.MoreTestClasses.Vb/PublicNamedIndex.vb @@ -1,19 +1,29 @@ -Public Class PublicNamedIndex(Of T) +Public Class PublicNamedIndex(Of T1, T2) - Private _valueToReturn As T + Private _value1ToReturn As T1 - Public WriteOnly Property ValueToReturn As T + Public WriteOnly Property Value1ToReturn As T1 Set - _valueToReturn = Value + _value1ToReturn = Value End Set End Property - Public ReadOnly Property Value( + Public ReadOnly Property Value1( Optional indexOne As Integer = 1, - Optional indexTwo As Integer = 2) As T + Optional indexTwo As Integer = 2) As T1 Get - Return _valueToReturn + Return _value1ToReturn End Get End Property + Public Property Value2SetValue As T2 + + Public WriteOnly Property Value2( + indexOne As Integer, + indexTwo As Integer) As T2 + Set + Value2SetValue = Value + End Set + End Property + End Class \ No newline at end of file diff --git a/AgileMapper.UnitTests/Configuration/WhenViewingMappingPlans.cs b/AgileMapper.UnitTests/Configuration/WhenViewingMappingPlans.cs index cb7ed5c0..5c90fea8 100644 --- a/AgileMapper.UnitTests/Configuration/WhenViewingMappingPlans.cs +++ b/AgileMapper.UnitTests/Configuration/WhenViewingMappingPlans.cs @@ -159,8 +159,8 @@ public void ShouldIncludeUnmappableReadOnlyArrayMemberDetails() public void ShouldIncludeUnmappableIndexedPropertyDetails() { string plan = Mapper - .GetPlanFor>>() - .ToANew>>(); + .GetPlanFor, PublicField>>() + .ToANew, PublicField>>(); plan.ShouldContain("requires index(es) - indexOne: int, indexTwo: int"); } diff --git a/AgileMapper.UnitTests/WhenMappingToNewComplexTypes.cs b/AgileMapper.UnitTests/WhenMappingToNewComplexTypes.cs index ad049c2c..4de273fa 100644 --- a/AgileMapper.UnitTests/WhenMappingToNewComplexTypes.cs +++ b/AgileMapper.UnitTests/WhenMappingToNewComplexTypes.cs @@ -136,34 +136,40 @@ public void ShouldConditionallyUseConstructorsWhereArgumentsAreNull() // See https://github.com/agileobjects/AgileMapper/issues/221 [Fact] - public void ShouldIgnoreSourceIndexedProperties() + public void ShouldIgnoreUnmappableSourceIndexedProperties() { - var source = new PublicNamedIndex> + var source = new PublicNamedIndex, PublicField> { - ValueToReturn = new PublicField { Value = "Test" } + Value1ToReturn = new PublicField { Value = "Test" } }; var result = Mapper .Map(source) - .ToANew>>(); + .ToANew, PublicField>>(); - result.ShouldNotBeNull().Value.ShouldBeNull(); + result.ShouldNotBeNull().Value1.ShouldNotBeNull().Value.ShouldBe("Test"); + result.ShouldNotBeNull().Value2.ShouldBeNull(); } // See https://github.com/agileobjects/AgileMapper/issues/221 [Fact] - public void ShouldIgnoreTargetIndexedProperties() + public void ShouldIgnoreUnmappableTargetIndexedProperties() { - var source = new PublicField> + var source = new PublicTwoFields, PublicField> { - Value = new PublicField { Value = "Hello!" } + Value1 = new PublicField { Value = 999 }, + Value2 = new PublicField { Value = "C ya!" } }; - var result = Mapper - .Map(source) - .ToANew>>(); + var target = new PublicNamedIndex, PublicField> + { + Value1ToReturn = new PublicField() + }; + + var result = Mapper.Map(source).OnTo(target); - result.ShouldNotBeNull().get_Value().ShouldBeNull(); + result.ShouldNotBeNull().get_Value1().ShouldNotBeNull().Value.ShouldBe(999); + result.ShouldNotBeNull().Value2SetValue.ShouldBeNull(); } #region Helper Classes diff --git a/AgileMapper/AgileMapper.csproj b/AgileMapper/AgileMapper.csproj index 05e3a9c0..07f6dcb4 100644 --- a/AgileMapper/AgileMapper.csproj +++ b/AgileMapper/AgileMapper.csproj @@ -21,6 +21,7 @@ MIT ./Icon.png - Fixing exact-name-matching constructor parameter mapping, re: #221 +- Partial support for VB.NET named, indexed properties, re: #221 - Performance improvements @@ -42,7 +43,7 @@ - $(DefineConstants);FEATURE_DRAWING;FEATURE_APPDOMAIN + $(DefineConstants);FEATURE_DRAWING;FEATURE_APPDOMAIN;FEATURE_DBNULL @@ -51,7 +52,7 @@ - $(DefineConstants);FEATURE_SERIALIZATION;FEATURE_DYNAMIC;FEATURE_DYNAMIC_ROOT_SOURCE;FEATURE_ISET;FEATURE_APPDOMAIN;FEATURE_ASSEMBLY_TRUST + $(DefineConstants);FEATURE_SERIALIZATION;FEATURE_DYNAMIC;FEATURE_DYNAMIC_ROOT_SOURCE;FEATURE_ISET;FEATURE_APPDOMAIN;FEATURE_ASSEMBLY_TRUST;FEATURE_MAKEINDEX;FEATURE_DBNULL @@ -61,7 +62,7 @@ - $(DefineConstants);FEATURE_DYNAMIC;FEATURE_ISET + $(DefineConstants);FEATURE_DYNAMIC;FEATURE_ISET;FEATURE_MAKEINDEX @@ -71,11 +72,11 @@ - $(DefineConstants);FEATURE_SERIALIZATION;FEATURE_DYNAMIC;FEATURE_DYNAMIC_ROOT_SOURCE;FEATURE_ISET + $(DefineConstants);FEATURE_SERIALIZATION;FEATURE_DYNAMIC;FEATURE_DYNAMIC_ROOT_SOURCE;FEATURE_ISET;FEATURE_MAKEINDEX - $(DefineConstants);FEATURE_SERIALIZATION;FEATURE_DYNAMIC;FEATURE_DYNAMIC_ROOT_SOURCE;FEATURE_ISET;FEATURE_APPDOMAIN;FEATURE_ASSEMBLY_TRUST + $(DefineConstants);FEATURE_SERIALIZATION;FEATURE_DYNAMIC;FEATURE_DYNAMIC_ROOT_SOURCE;FEATURE_ISET;FEATURE_APPDOMAIN;FEATURE_ASSEMBLY_TRUST;FEATURE_MAKEINDEX;FEATURE_DBNULL diff --git a/AgileMapper/DataSources/EnumerableDataSource.cs b/AgileMapper/DataSources/EnumerableDataSource.cs index c81e7c23..8f377dbb 100644 --- a/AgileMapper/DataSources/EnumerableDataSource.cs +++ b/AgileMapper/DataSources/EnumerableDataSource.cs @@ -118,7 +118,7 @@ private static Expression GetForwardLinkSelection(Expression sourceEnumerable, IMemberMapperData mapperData) { var funcTypes = new[] { linkParameter.Type, forwardLink.Type }; - var forwardLinkAccess = forwardLink.GetAccess(linkParameter); + var forwardLinkAccess = forwardLink.GetReadAccess(linkParameter); var forwardLinkLambda = Expression.Lambda( Expression.GetFuncType(funcTypes), @@ -150,7 +150,7 @@ private static Expression GetLinkOrdering( var orderMemberAccess = Expression.MakeMemberAccess( (orderMember.DeclaringType != linkParameter.Type) - ? forwardLink.GetAccess(linkParameter) + ? forwardLink.GetReadAccess(linkParameter) : linkParameter, orderMember); diff --git a/AgileMapper/Extensions/Internal/ReflectionExtensions.cs b/AgileMapper/Extensions/Internal/ReflectionExtensions.cs index 64941d22..c0cafc3a 100644 --- a/AgileMapper/Extensions/Internal/ReflectionExtensions.cs +++ b/AgileMapper/Extensions/Internal/ReflectionExtensions.cs @@ -63,5 +63,29 @@ public static IEnumerable QueryTypes(this Assembly assembly) return ex.Types.WhereNotNull(); } } + + public static IEnumerable QueryRequiredParameters( + this MethodInfo method) + { + return method.GetParameters().QueryRequired(); + } + + public static IEnumerable QueryRequired( + this IEnumerable parameters) + { + return parameters.Filter(p => + { + if (p.IsOptional) + { + return false; + } + +#if FEATURE_DBNULL + return p.DefaultValue == DBNull.Value; +#else + return p.DefaultValue.GetType().Name == "DBNull"; +#endif + }); + } } } diff --git a/AgileMapper/MapperContextExtensions.cs b/AgileMapper/MapperContextExtensions.cs index 433facbc..b5d94e70 100644 --- a/AgileMapper/MapperContextExtensions.cs +++ b/AgileMapper/MapperContextExtensions.cs @@ -42,7 +42,7 @@ public static Expression GetIdentifierOrNull( var identifier = context.GetIdentifierOrNull(key.Type); - return identifier?.GetAccess(subject); + return identifier?.GetReadAccess(subject); }); } diff --git a/AgileMapper/Members/Member.cs b/AgileMapper/Members/Member.cs index e36d748c..121efa22 100644 --- a/AgileMapper/Members/Member.cs +++ b/AgileMapper/Members/Member.cs @@ -1,6 +1,8 @@ namespace AgileObjects.AgileMapper.Members { using System; + using System.Collections.Generic; + using System.Linq; using System.Reflection; #if NET35 using Microsoft.Scripting.Ast; @@ -30,7 +32,7 @@ private Member( Type type, MemberInfo memberInfo, IAccessFactory accessFactory = null, - bool isIndexed = false, + IList requiredIndexes = null, bool isReadable = true, bool isWriteable = true, bool isRoot = false) @@ -40,7 +42,7 @@ private Member( memberInfo.DeclaringType, type, accessFactory, - isIndexed, + requiredIndexes, isReadable, isWriteable, isRoot) @@ -54,7 +56,7 @@ private Member( Type declaringType, Type type, IAccessFactory accessFactory = null, - bool isIndexed = false, + IList requiredIndexes = null, bool isReadable = true, bool isWriteable = true, bool isRoot = false) @@ -64,7 +66,7 @@ private Member( DeclaringType = declaringType; Type = type; _accessFactory = accessFactory; - IsIndexed = isIndexed; + RequiredIndexes = requiredIndexes ?? Enumerable.EmptyArray; IsReadable = isReadable; IsWriteable = isWriteable; IsRoot = isRoot; @@ -140,21 +142,16 @@ public static Member Field(FieldInfo fieldInfo) public static Member Property(PropertyInfo propertyInfo) { - var isReadable = propertyInfo.IsReadable(); - var isWritable = propertyInfo.IsWritable(); - - var isIndexed = - isReadable && propertyInfo.GetGetter().GetParameters().Any() || - isWritable && propertyInfo.GetSetter().GetParameters().Length > 1; + var propertyInfoWrapper = PropertyInfoWrapper.For(propertyInfo); return new Member( MemberType.Property, propertyInfo.PropertyType, propertyInfo, - new PropertyInfoWrapper(propertyInfo), - isIndexed, - isReadable, - isWritable); + propertyInfoWrapper, + propertyInfoWrapper.RequiredIndexes, + propertyInfoWrapper.IsReadable, + propertyInfoWrapper.IsWritable); } public static Member GetMethod(MethodInfo methodInfo) @@ -163,7 +160,8 @@ public static Member GetMethod(MethodInfo methodInfo) MemberType.GetMethod, methodInfo.ReturnType, methodInfo, - new MethodInfoWrapper(methodInfo)); + new MethodInfoWrapper(methodInfo), + isWriteable: false); } public static Member SetMethod(MethodInfo methodInfo) @@ -172,6 +170,7 @@ public static Member SetMethod(MethodInfo methodInfo) MemberType.SetMethod, methodInfo.GetParameters()[0].ParameterType, methodInfo, + new MethodInfoWrapper(methodInfo), isReadable: false); } @@ -215,7 +214,7 @@ public static Member DictionaryEntry(string sourceMemberName, DictionaryTargetMe public bool IsSimple { get; } - public bool IsIndexed { get; set; } + public IList RequiredIndexes { get; } public bool IsReadable { get; } @@ -230,7 +229,7 @@ public static Member DictionaryEntry(string sourceMemberName, DictionaryTargetMe public bool HasAttribute() => MemberInfo?.HasAttribute() == true; - public Expression GetAccess(Expression instance) + public Expression GetReadAccess(Expression instance) { if (!IsReadable || (_accessFactory == null)) { @@ -242,7 +241,22 @@ public Expression GetAccess(Expression instance) instance = Expression.Convert(instance, DeclaringType); } - return _accessFactory.GetAccess(instance); + return _accessFactory.GetReadAccess(instance); + } + + public Expression GetAssignment(Expression instance, Expression value) + { + if (!IsWriteable || (_accessFactory == null)) + { + return Type.ToDefaultExpression(); + } + + if (!instance.Type.IsAssignableTo(DeclaringType)) + { + instance = Expression.Convert(instance, DeclaringType); + } + + return _accessFactory.GetAssignment(instance, value); } public Member WithType(Type runtimeType) @@ -254,7 +268,7 @@ public Member WithType(Type runtimeType) runtimeType, MemberInfo, _accessFactory, - IsIndexed, + RequiredIndexes, IsReadable, IsWriteable, IsRoot); @@ -265,7 +279,7 @@ public Member WithType(Type runtimeType) Name, DeclaringType, runtimeType, - isIndexed: IsIndexed, + requiredIndexes: RequiredIndexes, isReadable: IsReadable, isWriteable: IsWriteable, isRoot: IsRoot); @@ -296,7 +310,9 @@ private static class TargetMemberCache private interface IAccessFactory { - Expression GetAccess(Expression instance); + Expression GetReadAccess(Expression instance); + + Expression GetAssignment(Expression instance, Expression value); } private class FieldInfoWrapper : IAccessFactory @@ -305,27 +321,168 @@ private class FieldInfoWrapper : IAccessFactory public FieldInfoWrapper(FieldInfo fieldInfo) => _fieldInfo = fieldInfo; - public Expression GetAccess(Expression instance) => Expression.Field(instance, _fieldInfo); + public Expression GetReadAccess(Expression instance) + => Expression.Field(instance, _fieldInfo); + + public Expression GetAssignment(Expression instance, Expression value) + => GetReadAccess(instance).AssignTo(value); } - private class PropertyInfoWrapper : IAccessFactory + private interface IPropertyAccessFactory : IAccessFactory { - private readonly PropertyInfo _propertyInfo; + bool IsReadable { get; } - public PropertyInfoWrapper(PropertyInfo propertyInfo) => _propertyInfo = propertyInfo; + bool IsWritable { get; } - public Expression GetAccess(Expression instance) => Expression.Property(instance, _propertyInfo); + IList RequiredIndexes { get; } + } + + private static class PropertyInfoWrapper + { + public static IPropertyAccessFactory For(PropertyInfo propertyInfo) + { + var getter = propertyInfo.GetGetter(); + var getterParameters = getter?.GetParameters(); + + var setter = propertyInfo.GetSetter(); + IList setterParameters; + + if (setter != null) + { + setterParameters = setter.GetParameters(); + var parameterCount = setterParameters.Count; + + if (parameterCount > 1) + { + var setterIndexes = new ParameterInfo[parameterCount - 1]; + setterIndexes.CopyFrom(setterParameters); + setterParameters = setterIndexes; + } + else + { + setterParameters = Enumerable.EmptyArray; + } + } + else + { + setterParameters = Enumerable.EmptyArray; + } + + if (getterParameters.NoneOrNull() && setterParameters.None()) + { + return new StandardPropertyInfoWrapper(propertyInfo); + } + + var arguments = (getterParameters ?? setterParameters) + .ProjectToArray(p => + { + var defaultValue = p.DefaultValue; +#if FEATURE_DBNULL + if (defaultValue == DBNull.Value) +#else + if (defaultValue.GetType().Name == "DBNull") +#endif + { + return p.ParameterType.ToDefaultExpression(); + } + + if (p.ParameterType.IsValueType()) + { + defaultValue = Convert.ChangeType(defaultValue, p.ParameterType); + } + + return Expression.Constant(defaultValue, p.ParameterType); + }); + + + return new IndexedPropertyInfoWrapper( + propertyInfo, + getter, + getterParameters ?? Enumerable.EmptyArray, + setter, + setterParameters, + arguments); + } + + private class StandardPropertyInfoWrapper : IPropertyAccessFactory + { + private readonly PropertyInfo _propertyInfo; + + public StandardPropertyInfoWrapper(PropertyInfo propertyInfo) + { + _propertyInfo = propertyInfo; + IsReadable = propertyInfo.IsReadable(); + IsWritable = propertyInfo.IsWritable(); + } + + public bool IsReadable { get; } + + public bool IsWritable { get; } + + public IList RequiredIndexes + => Enumerable.EmptyArray; + + public Expression GetReadAccess(Expression instance) + => Expression.Property(instance, _propertyInfo); + + public Expression GetAssignment(Expression instance, Expression value) + => GetReadAccess(instance).AssignTo(value); + } + + private class IndexedPropertyInfoWrapper : IPropertyAccessFactory + { + private readonly PropertyInfo _propertyInfo; + private readonly MethodInfo _setter; + private readonly Expression[] _arguments; + + public IndexedPropertyInfoWrapper( + PropertyInfo propertyInfo, + MethodInfo getter, + IEnumerable getterParameters, + MethodInfo setter, + IEnumerable setterParameters, + Expression[] arguments) + { + _propertyInfo = propertyInfo; + _setter = setter; + _arguments = arguments; + IsReadable = getter != null; + IsWritable = setter != null; + + RequiredIndexes = IsReadable + ? getterParameters.QueryRequired().ToList() + : setterParameters.QueryRequired().ToList(); + } + + public bool IsReadable { get; } + + public bool IsWritable { get; } + + public IList RequiredIndexes { get; } + + public Expression GetReadAccess(Expression instance) + => Expression.Property(instance, _propertyInfo, _arguments); + + public Expression GetAssignment(Expression instance, Expression value) + => Expression.Call(instance, _setter, _arguments.Append(value)); + } } private class MethodInfoWrapper : IAccessFactory { private readonly MethodInfo _methodInfo; - public MethodInfoWrapper(MethodInfo methodInfo) => _methodInfo = methodInfo; + public MethodInfoWrapper(MethodInfo methodInfo) + { + _methodInfo = methodInfo; + } - public Expression GetAccess(Expression instance) => Expression.Call(instance, _methodInfo); - } + public Expression GetReadAccess(Expression instance) + => Expression.Call(instance, _methodInfo); + public Expression GetAssignment(Expression instance, Expression value) + => Expression.Call(instance, _methodInfo, value); + } #endregion } } \ No newline at end of file diff --git a/AgileMapper/Members/MemberCache.cs b/AgileMapper/Members/MemberCache.cs index 28984a04..353be7f6 100644 --- a/AgileMapper/Members/MemberCache.cs +++ b/AgileMapper/Members/MemberCache.cs @@ -41,16 +41,24 @@ public IList GetTargetMembers(Type targetType) { return _membersCache.GetOrAdd(TypeKey.ForTargetMembers(targetType), key => { - if (key.Type == typeof(object) || key.Type.IsEnum() || key.Type.IsEnumerable()) + var type = key.Type; + + if (type == typeof(string) || type.IsEnum() || + type == typeof(object) || type.IsEnumerable()) + { + return Enumerable.EmptyArray; + } + + if (type.IsValueType() && type.IsFromBcl()) { return Enumerable.EmptyArray; } - var fields = GetFields(key.Type, AllExceptBclComplexTypes); - var properties = GetProperties(key.Type, AllExceptBclComplexTypes); - var methods = GetMethods(key.Type, OnlyCallableSetters, Member.SetMethod); + var fields = GetFields(type, AllExceptBclComplexTypes); + var properties = GetProperties(type, AllExceptBclComplexTypes); + var methods = GetMethods(type, OnlyCallableSetters, Member.SetMethod); - var constructorParameterNames = key.Type + var constructorParameterNames = type .GetPublicInstanceConstructors() .SelectMany(ctor => ctor.GetParameters().ProjectToArray(p => p.Name)) .Distinct() @@ -65,7 +73,7 @@ public IList GetTargetMembers(Type targetType) }) .ToArray(); - return GetAllMembers(key.Type, GetTargetMembers, fieldsAndProperties, methods); + return GetAllMembers(type, GetTargetMembers, fieldsAndProperties, methods); }); } @@ -135,7 +143,7 @@ private static bool AllExceptBclComplexTypes(PropertyInfo property) private static bool OnlyGettable(PropertyInfo property) { var getter = property.GetGetter(); - return getter != null && getter.GetParameters().None(); + return getter != null && getter.QueryRequiredParameters().None(); } #endregion diff --git a/AgileMapper/Members/MemberExtensionMethods.cs b/AgileMapper/Members/MemberExtensionMethods.cs index 6f7bb3a7..365c2ff2 100644 --- a/AgileMapper/Members/MemberExtensionMethods.cs +++ b/AgileMapper/Members/MemberExtensionMethods.cs @@ -89,6 +89,17 @@ public static bool IsUnmappable(this QualifiedMember member, out string reason) return false; } + if (member.LeafMember.RequiredIndexes.Any()) + { + var indexes = string.Join(", ", member + .LeafMember + .RequiredIndexes + .ProjectToArray(p => p.Name + ": " + p.ParameterType.GetFriendlyName())); + + reason = "requires index(es) - " + indexes; + return true; + } + if (!member.IsReadOnly) { reason = null; @@ -113,19 +124,6 @@ public static bool IsUnmappable(this QualifiedMember member, out string reason) return true; } - if (member.IsIndexed) - { - var property = (PropertyInfo)member.LeafMember.MemberInfo; - - var indexes = string.Join(", ", property - .GetGetter() - .GetParameters() - .ProjectToArray(p => p.Name + ": " + p.ParameterType.GetFriendlyName())); - - reason = "requires index(es) - " + indexes; - return true; - } - reason = null; return false; } @@ -164,7 +162,7 @@ public static Expression GetQualifiedAccess(this IEnumerable memberChain // Skip(1) because the 0th member is the mapperData.SourceObject: return memberChain.Skip(1).Aggregate( parentInstance, - (accessSoFar, member) => member.GetAccess(accessSoFar)); + (accessSoFar, member) => member.GetReadAccess(accessSoFar)); } [DebuggerStepThrough] @@ -262,38 +260,6 @@ public static Member[] RelativeTo(this Member[] memberChain, Member[] otherMembe return relativeMemberChain; } - #region PopulationFactoriesByMemberType - - private delegate Expression PopulationFactory(Expression instance, Member member, Expression value); - - private static Expression AssignMember(Expression instance, Member targetMember, Expression value) - => targetMember.GetAccess(instance).AssignTo(value); - - private static Expression CallSetMethod(Expression instance, Member targetMember, Expression value) - => Expression.Call(instance, targetMember.Name, EmptyTypeArray, value); - - #endregion - - public static Expression GetPopulation(this Member targetMember, Expression instance, Expression value) - { - var populationFactory = GetPopulationFactory(targetMember); - var population = populationFactory.Invoke(instance, targetMember, value); - - return population; - } - - private static PopulationFactory GetPopulationFactory(Member targetMember) - { - return targetMember.MemberType switch - { - MemberType.Field => AssignMember, - MemberType.Property => AssignMember, - MemberType.SetMethod => CallSetMethod, - _ => throw new NotSupportedException( - "No PopulationFactory defined for MemberType") - }; - } - public static QualifiedMember ToSourceMemberOrNull( this Expression memberAccess, MapperContext mapperContext) diff --git a/AgileMapper/Members/QualifiedMember.cs b/AgileMapper/Members/QualifiedMember.cs index ea501876..7d8ea31d 100644 --- a/AgileMapper/Members/QualifiedMember.cs +++ b/AgileMapper/Members/QualifiedMember.cs @@ -38,7 +38,7 @@ protected QualifiedMember(Member[] memberChain, QualifiedMember adaptedMember) foreach (var childMember in adaptedMember._childMemberCache.Values) { - _childMemberCache.GetOrAdd(childMember.LeafMember, m => childMember); + _childMemberCache.GetOrAdd(childMember.LeafMember, _ => childMember); } } @@ -180,8 +180,6 @@ public static QualifiedMember Create(Member[] memberChain, MapperContext mapperC public bool IsReadable => LeafMember.IsReadable; public bool IsReadOnly { get; set; } - - public bool IsIndexed => LeafMember.IsIndexed; public bool IsRecursion { get; } @@ -299,7 +297,7 @@ public virtual bool Matches(IQualifiedMember otherMember) } public virtual Expression GetAccess(Expression instance, IMemberMapperData mapperData) - => LeafMember.GetAccess(instance); + => LeafMember.GetReadAccess(instance); public Expression GetQualifiedAccess(Expression parentInstance) => MemberChain.GetQualifiedAccess(parentInstance); @@ -337,7 +335,7 @@ public virtual Expression GetHasDefaultValueCheck(IMemberMapperData mapperData) => this.GetAccess(mapperData).GetIsDefaultComparison(); public virtual Expression GetPopulation(Expression value, IMemberMapperData mapperData) - => LeafMember.GetPopulation(mapperData.TargetInstance, value); + => LeafMember.GetAssignment(mapperData.TargetInstance, value); public virtual void MapCreating(Type sourceType) { diff --git a/AgileMapper/Queryables/Converters/ComplexTypeToNullComparisonConverter.cs b/AgileMapper/Queryables/Converters/ComplexTypeToNullComparisonConverter.cs index c59ff778..59957010 100644 --- a/AgileMapper/Queryables/Converters/ComplexTypeToNullComparisonConverter.cs +++ b/AgileMapper/Queryables/Converters/ComplexTypeToNullComparisonConverter.cs @@ -46,7 +46,7 @@ private static Expression Convert(BinaryExpression comparison, IQueryProjectionM out var entityMemberIdMember)) { return entityMemberIdMember - .GetAccess(entityParentAccess) + .GetReadAccess(entityParentAccess) .GetIsNotDefaultComparison(); }