Mapster
Mapster copied to clipboard
Can't map to Nullable<T> property
The following code just won't work:
public class MyClass
{
public string Code { get; set; }
public string Name { get; set; }
public MyStruct? StructValue { get; set; }
}
public struct MyStruct
{
public Enum1 Value1 { get; set; }
public Enum2 Value2 { get; set; }
}
public static TypeAdapterConfig GetConfig()
{
var config = new TypeAdapterConfig();
config.NewConfig<DataRow, MyClass>()
.Map(c => c.Code, dr => dr.Field<string>("Code"))
.Map(c => c.Name, dr => dr.Field<string>("Name"))
.Map(c => c.StructValue, dr => dr, dr => ShouldMapStructValue(dr))
.IgnoreNonMapped(true);
config.NewConfig<DataRow, MyStruct>()
.Map(c => c.Value1, dr => EnumHelper.ParseEnum1(dr.Field<string>("Enum1")))
.Map(c => c.Value2, dr => EnumHelper.ParseEnum2(dr.Field<string>("Enum2")))
.IgnoreNonMapped(true);
}
public static void Main(params string[] args)
{
var container = new DryIoc.Container();
container.RegisterInstance(GetConfig());
container.Register<IMapper, ServiceMapper>(Reuse.Scoped);
var mapper = container.Resolve<IMapper>();
DataRow dataRow = GetDataRowFromDatabase();
var myClass = mapper.Map<MyClass>(dataRow);
}
The last line (the one where the mapping itself is done) throws the following exception:
---> Mapster.CompileException: Error while compiling
source=System.Data.DataRow
destination=System.Nullable`1[MyNameSpace.MyStruct]
type=Map
---> System.InvalidOperationException: Cannot convert immutable type, please consider using 'MapWith' method to create mapping
at Mapster.Adapters.PrimitiveAdapter.ConvertType(Expression source, Type destinationType, CompileArgument arg)
at Mapster.Adapters.PrimitiveAdapter.CreateExpressionBody(Expression source, Expression destination, CompileArgument arg)
at Mapster.Adapters.BaseAdapter.CreateAdaptFunc(CompileArgument arg)
at Mapster.TypeAdapterConfig.CreateMapExpression(CompileArgument arg)
--- End of inner exception stack trace ---
at Mapster.TypeAdapterConfig.CreateMapExpression(CompileArgument arg)
at Mapster.TypeAdapterConfig.CreateInlineMapExpression(Type sourceType, Type destinationType, MapType mapType, CompileContext context, MemberMapping mapping)
at Mapster.Adapters.BaseAdapter.CreateAdaptExpressionCore(Expression source, Type destinationType, CompileArgument arg, MemberMapping mapping, Expression destination)
at Mapster.Adapters.BaseAdapter.CreateAdaptExpression(Expression source, Type destinationType, CompileArgument arg, MemberMapping mapping, Expression destination)
at Mapster.Adapters.ClassAdapter.CreateBlockExpression(Expression source, Expression destination, CompileArgument arg)
at Mapster.Adapters.BaseAdapter.CreateBlockExpressionBody(Expression source, Expression destination, CompileArgument arg)
at Mapster.Adapters.BaseAdapter.CreateExpressionBody(Expression source, Expression destination, CompileArgument arg)
at Mapster.Adapters.BaseAdapter.CreateAdaptFunc(CompileArgument arg)
at Mapster.TypeAdapterConfig.CreateMapExpression(CompileArgument arg)
--- End of inner exception stack trace ---
at Mapster.TypeAdapterConfig.CreateMapExpression(CompileArgument arg)
at Mapster.TypeAdapterConfig.CreateMapExpression(TypeTuple tuple, MapType mapType)
at Mapster.TypeAdapterConfig.CreateDynamicMapExpression(TypeTuple tuple)
at Mapster.TypeAdapterConfig.<GetDynamicMapFunction>b__66_0[TDestination](TypeTuple tuple)
at Mapster.TypeAdapterConfig.<>c__DisplayClass55_0`1.<AddToHash>b__0(TypeTuple types)
at System.Collections.Concurrent.ConcurrentDictionary`2.GetOrAdd(TKey key, Func`2 valueFactory)
at Mapster.TypeAdapterConfig.AddToHash[T](ConcurrentDictionary`2 hash, TypeTuple key, Func`2 func)
at Mapster.TypeAdapterConfig.GetDynamicMapFunction[TDestination](Type sourceType)
at MapsterMapper.Mapper.Map[TDestination](Object source)
at MapsterMapper.ServiceMapper.Map[TDestination](Object source)
[...] --- removed for privacy reasons
same here
You have to create a mapping for the nullable types as well.
NewConfig<DataRow?, MyStruct?>
I'm guessing assumptions can't be made that null maps to null, or maybe unwrapping is too expensive, but whatever the case, if you have a nullable you need to specify that as another Map.