public interface IDataLocalizer
{
public CultureInfo CultureInfo { get; set; }
}
public interface ILocalizerDto : IMyDto
{
public string CultureName { get; set; }
public string CultureDisplayName { get; set; }
public CultureInfo CultureInfo { get; }
}
public abstract class DataLocalizerRegister<TLocalizerDto, TDataLocalizer>
where TLocalizerDto : ILocalizerDto where TDataLocalizer : IDataLocalizer
{
public override void Register(TypeAdapterConfig config)
{
var parameter = Expression.Parameter(typeof(TDataLocalizer), "localizer");
Expression memberAccessExp = Expression.Property(parameter, nameof(IDataLocalizer.CultureInfo));
var dtoToEntitySetter = config.NewConfig<TLocalizerDto, TDataLocalizer>()
.Ignore(Expression.Lambda<Func<TDataLocalizer, object>>(memberAccessExp, parameter))
.AfterMapping((dto, localizer) => localizer.CultureInfo = CultureInfo.GetCultureInfo(dto.CultureName));
var entityToDtoSetter = config.NewConfig<TDataLocalizer, TLocalizerDto>()
.Map(dto => dto.CultureName, m => m.CultureInfo.Name)
.Map(dto => dto.CultureDisplayName, m => m.CultureInfo.DisplayName);
RegisterCustomMember(dtoToEntitySetter, entityToDtoSetter);
}
protected abstract override void RegisterCustomMember(
TypeAdapterSetter<TLocalizerDto, TDataLocalizer> dtoToEntitySetter,
TypeAdapterSetter<TDataLocalizer, TLocalizerDto> entityToDtoSetter);
}
After debug,
memberAccessExp is worked and its debug view is "$localizer.CultureInfo" , so simple :)
'm => m.CultureInfo.Name` is not worked and its debug view is
and all the lambda in the method Register will convert toExpression like m => m.CultureInfo.Name, contains (My.Models.Abstraction.IDataLocalizer) case.
Stack trace:
System.ArgumentException: Allow only member access (eg. obj => obj.Child.Name) (Parameter 'lambda')
at Mapster.Utils.ExpressionEx.GetMemberPath(LambdaExpression lambda, Boolean firstLevelOnly, Boolean noError)
at Mapster.TypeAdapterSetter`2.Map[TDestinationMember,TSourceMember](Expression`1 member, Expression`1 source, Expression`1 shouldMap)
at My.Services.Mapping.Mapster.Registers.DataLocalizerRegister`2.Register(TypeAdapterConfig config) in /somewhere/DataLocalizerRegister.cs:line 17
at Mapster.TypeAdapterConfig.Apply(IEnumerable`1 registers)
at Mapster.TypeAdapterConfig.Scan(Assembly[] assemblies)
...
If I change the class DataLocalizerRegister like below, it's working without any error.
public abstract class DataLocalizerRegister<TLocalizerDto, TDataLocalizer>
where TLocalizerDto : AbstractLocalizerDto where TDataLocalizer : AbstractDataLocalizer
AbstractLocalizerDto and AbstractDataLocalizer are classes, not like the ILocalizerDto and IDataLocalizer they are interfaces.
I think this is a bug, m => m.CultureInfo.Name lambda is simple, method Mapster.Utils.ExpressionEx.GetMemberPath should support in this case.
After debug,
memberAccessExp
is worked and its debug view is "$localizer.CultureInfo" , so simple :) 'm => m.CultureInfo.Name` is not worked and its debug view isand all the lambda in the method
Register
will convert toExpression
likem => m.CultureInfo.Name
, contains(My.Models.Abstraction.IDataLocalizer)
case.Stack trace:
If I change the class
DataLocalizerRegister
like below, it's working without any error.AbstractLocalizerDto
andAbstractDataLocalizer
are classes, not like theILocalizerDto
andIDataLocalizer
they are interfaces.I think this is a bug,
m => m.CultureInfo.Name
lambda is simple, methodMapster.Utils.ExpressionEx.GetMemberPath
should support in this case..Net 7.0 C# 11.0 Mapster 7.3.0