Open kzeratal opened 2 years ago
@kzeratal Can you share the mapping config and your custom type conversion code? Or alternatively set up a minimal test case if that's easier for you.
The following are the config and classes.
public class DateTimeConfig : IRegister
{
public void Register(TypeAdapterConfig config)
{
config.ForType<DateTime, long>()
.Map(dest => dest, src => src.ToLong());
config.ForType<long, DateTime>()
.Map(dest => dest, src => src.ToDateTime());
}
}
Extensions look like
public long ToLong(DateTime time)
{
return new DateTimeOffset(time).ToUnixTimeSeconds();
}
public DateTime ToDateTime(long value)
{
return new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(source);
}
public class C1
{
public DateTime Time { get; set; }
}
public class C2
{
public long Time { get; set; }
}
and the usage
var c1 = new C1 { Time = DateTime.UtcNow };
var c2Test1 = dbCotext.C1.ProjectToType<C2>().ToList().First(); // failed using EF 6
var c2Test2 = c1.Adapt<C2>(); // also failed at simple mapping, both two c2 objects' Time are 0
Have you added breakpoints to the ToLong() and ToDateTime() methods and verified that they are being called as expected?
Well, they are not being called.
I see. You have also checked that the DateTimeConfig.Register() method is called?
Yes, the register was executed.
If there is no config, an System.InvalidCastException: 'Invalid cast from 'DateTime' to 'Int64'.'
will occur.
Hello @andrerav I think I know what this is about. Primitives do not support custom mapping. I described it in this #561. I even developed a specific solution) I'll test it on this case and report the result
It needs some work, but it definitely works as I planned when the mapping To primitive.
[TestMethod]
public void MappingDatetimeToLong()
{
TypeAdapterConfig.GlobalSettings.ForType(typeof(Source407), typeof(Destination407))
.MapToTargetPrimitive(true);
TypeAdapterConfig<DateTime, long>
.NewConfig()
.MapToTargetWith((source, target) => true ? new DateTimeOffset(source).ToUnixTimeSeconds() : target);
TypeAdapterConfig<long, DateTime>
.NewConfig()
.MapToTargetWith((source, target) => true ? new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(source) : target);
var fromC1 = new DateTime(2023, 10, 27);
var fromC2 = new DateTimeOffset(new DateTime(2025, 11, 23)).ToUnixTimeSeconds();
var c1 = new Source407 { Time = fromC1 };
var c2 = new Destination407 { Time = fromC2 };
var _result = c1.Adapt<Destination407>(); // Work
var _resultLongtoDateTime = c2.Adapt<Source407>();
_result.Time.ShouldBe(new DateTimeOffset(new DateTime(2023, 10, 27)).ToUnixTimeSeconds()); // Work
// _resultLongtoDateTime.Time.ShouldBe(new DateTime(2025, 11, 23)); // ClassAdapter - not work;
}
public class Source407
{
public DateTime Time { get; set; }
}
public class Destination407
{
public long Time { get; set; }
}
update must work because Datetime not primitive. I just set the settings for the update script
Work all
[TestMethod]
public void MappingDatetimeToLong()
{
TypeAdapterConfig.GlobalSettings.ForType(typeof(Source407), typeof(Destination407))
.MapToTargetPrimitive(true);
TypeAdapterConfig<DateTime, long>
.NewConfig()
.MapToTargetWith((source, target) => true ? new DateTimeOffset(source).ToUnixTimeSeconds() : target);
TypeAdapterConfig<long, DateTime>
.NewConfig()
.MapToTargetWith((source, target) => true ? new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(source).Date : target);
var emptySource = new Source407() { Time = DateTime.UtcNow.Date };
var fromC1 = new DateTime(2023, 10, 27);
var fromC2 = new DateTimeOffset(new DateTime(2025, 11, 23)).ToUnixTimeSeconds();
var c1 = new Source407 { Time = fromC1 };
var c2 = new Destination407 { Time = fromC2 };
var _result = c1.Adapt<Destination407>(); // Work
var _resultLongtoDateTime = c2.Adapt(emptySource); // work
_result.Time.ShouldBe(new DateTimeOffset(new DateTime(2023, 10, 27)).ToUnixTimeSeconds()); // Work
_resultLongtoDateTime.Time.ShouldBe(new DateTime(2025, 11, 22).Date); // work but it turns out to be a day less. Perhaps this is how it was intended
}
@andrerav Yes, this is simply due to the lack of support for custom mapping processing from primitive type
@andrerav in #650 i send this function.
I have a class
A
that has aDateTime
property, and classB
that has along
property. Both properties have the same name. I've setup the rule for typeDateTime
converting tolong
in a configC1
which implementsIRegister
interface. And of course a configC2
forA
converting toB
But when I map fromA
toB
, thatDateTime
property will always 0, unless I set the mapping rule in configC2
.