Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Properties do not map properly #407

Open
kzeratal opened this issue Feb 24, 2022 · 11 comments
Open

Properties do not map properly #407

kzeratal opened this issue Feb 24, 2022 · 11 comments

Comments

@kzeratal
Copy link

I have a class A that has a DateTime property, and class B that has a long property.
Both properties have the same name.
I've setup the rule for type DateTime converting to long in a config C1 which implements IRegister interface.
And of course a config C2 for A converting to B
But when I map from A to B, that DateTime property will always 0, unless I set the mapping rule in config C2.

@kzeratal kzeratal changed the title Properties' do not map properly Properties do not map properly Feb 24, 2022
@andrerav
Copy link
Contributor

@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.

@kzeratal
Copy link
Author

kzeratal commented Feb 24, 2022

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

@andrerav
Copy link
Contributor

Have you added breakpoints to the ToLong() and ToDateTime() methods and verified that they are being called as expected?

@kzeratal
Copy link
Author

Well, they are not being called.

@andrerav
Copy link
Contributor

I see. You have also checked that the DateTimeConfig.Register() method is called?

@kzeratal
Copy link
Author

Yes, the register was executed.
If there is no config, an System.InvalidCastException: 'Invalid cast from 'DateTime' to 'Int64'.' will occur.

@DocSvartz
Copy link

DocSvartz commented Oct 27, 2023

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

@DocSvartz
Copy link

DocSvartz commented Oct 27, 2023

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

@DocSvartz
Copy link

DocSvartz commented Oct 27, 2023

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
}

@DocSvartz
Copy link

DocSvartz commented Oct 27, 2023

@andrerav Yes, this is simply due to the lack of support for custom mapping processing from primitive type

@DocSvartz
Copy link

DocSvartz commented Oct 28, 2023

@andrerav in #650 i send this function.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants