Home > Enterprise >  Automapper TMember returns 0 instead of expected value
Automapper TMember returns 0 instead of expected value

Time:10-17

Public Class NodeInfo
    Public Property X As Double
End Class

Public Class NetNode
    Public Property X As Double
End Class

For the models above, I have the following map. The value of the "X" property of the source object is 0.00013. I am expecting the value of "o" to be the same but it is always 0. If I return "s.X" instead of "o" it works fine but I thought that the TMember should have returned the corresponding property value as well.

CreateMap(Of NodeInfo, NetNode)().
    ForMember(Function(n) n.X, 
              Sub(opt As IMemberConfigurationExpression(Of NodeInfo, NetNode, Double))
                  opt.MapFrom(Function(s As NodeInfo, d As NetNode, o As Double, ctx As ResolutionContext)
                                Return o
                              End Function)
              End Sub).ReverseMap()

I am using the following overloads.

IMemberConfigurationExpression<TSource, TDestination, TMember>

MapFrom<TResult>(Func<TSource, TDestination, TMember, ResolutionContext, TResult> mappingFunction);

So my full expression for that overload is as following:

Sub IMemberConfigurationExpression(Of NodeInfo,NetNode,Double).MapFrom(Of Double)(mappingFunction As Func(Of NodeInfo,NetNode,Double,ResolutionContext,Double))

Can somebody explain me what I am missing?

CodePudding user response:

It turns out that hat TMember represents the destination member of the destination object.

Thanks to pfx's answer to this question.

Since I needed both source and destination members inside ForAllMembers,

1- I retrieved destination members from ForAllMembers by opt.DestinationMember

Sub(opt As IMemberConfigurationExpression(Of TSource, TDestination, Object))
                                Dim destinationProperty = TryCast(opt.DestinationMember, PropertyInfo)
Dim destinationProperty = TryCast(opt.DestinationMember, PropertyInfo)
                                If destinationProperty Is Nothing Then Return
                                Dim pd = TypeDescriptor.GetProperties(destinationProperty.DeclaringType).OfType(Of PropertyWithParamDescriptor).FirstOrDefault(Function(p) p.Name = destinationProperty.Name)
                                If pd IsNot Nothing AndAlso pd.CanWrite AndAlso pd.Unit IsNot Nothing AndAlso sourceType.GetProperty(destinationProperty.Name) IsNot Nothing Then
                                    Dim unit = pd.Unit

2- Used ConvertUsing to reach the source member and provided the destination member as parameter to the method I am using in my ConvertUsing.

opt.ConvertUsing(New UnitConvertor(Of Double)(destinationProperty, GetType(TSource), unit))

UnitConvertor

Public Class UnitConvertor(Of T As Structure)
    Implements IValueConverter(Of T, Object)

    Dim _PropertyInfo As PropertyInfo
    Dim _SourceType As Type
    Dim _Unit As UnitAttribute

    Public Sub New(propertyInfo As PropertyInfo, sourceType As Type, unit As UnitAttribute)
        _PropertyInfo = propertyInfo
        _SourceType = sourceType
        _Unit = unit
    End Sub

    Public Function Convert(sourceMember As T, ctx As ResolutionContext) As Object Implements IValueConverter(Of T, Object).Convert
        Dim unitName = ctx.GetUnitName(_SourceType, _PropertyInfo.Name)
        Dim tUnit = If(unitName.HasValue, New Units(_Unit.Unit.UnitType, unitName), CType(Nothing, Units))

        Return CType(If(tUnit?.C2SIUnit(System.Convert.ToDouble(sourceMember)), sourceMember), T)
    End Function

End Class
  • Related