2

I have the following two classes (many properties elided for brevity).

Service Layer POCO:

public class TicketFlag
{
    public ContactKey ContactKey;
}

LINQ to SQL generated POCO:

public class TicketFlag
{
    public string ContactKey;    
}

When trying to use AutoMapper to map between these two on service calls -> database save, I'm getting the following exception:

Exception of type 'AutoMapper.AutoMapperMappingException' was thrown.
 ---> System.ArgumentException: Type 'ContactKey' does not have a default constructor

ContactKey does not have a default constructor on purpose. Basically, it takes a string and a list of objects and can serialize/deserialize itself.

I have tried creating a mapping function (and it's inverse) like so:

Mapper.CreateMap<string, ContactKey>().ConvertUsing(s => ContactKeySerializer.Serialize(s));

But I'm still getting complaints because ContactKey doesn't have a default constructor.

Is there a way to get AutoMapper to not use the default constructor to do it's property mapping? Really, just mapping properties on the ContactKey isn't sufficient - I need to have it call the constructor, or get spit out from my ContactKeySerializer class.

Nicolas Webb
  • 1,312
  • 10
  • 22
  • Are you sure its not because they're `fields` and not `properties`? – Khan Sep 26 '13 at 18:51
  • They are fields, thanks for pointing that out. Editing now to clarify. Unsure of why that matters, though. Maybe I need to RTFM :)? – Nicolas Webb Sep 26 '13 at 18:54
  • Can you show the Mapper.Map call, specially the one where you think your CreateMap is used? – rene Sep 26 '13 at 19:05
  • It works for me as-is. Did you eliminate something from your sample code that caused the problem? – Tim S. Sep 26 '13 at 19:33
  • @Tim S There's some helper classes that cache the mapping that I did remove. It could be something there. I'll check. Also going to try your answer (with the ResolveUsing) - not used that one before. – Nicolas Webb Sep 26 '13 at 20:31

2 Answers2

2

First, you should probably be using properties for these things, not fields. However, I doubt that's part of your problem.

Instead of trying to create a map from string to ContactKey, you could try to make this part of the map from one TicketFlag to the other:

Mapper.CreateMap<LINQtoSQL.TicketFlag, Service.Layer.TicketFlag>()
 .ForMember(dest => dest.ContactKey,
 mem => mem.ResolveUsing(src => ContactKeySerializer.Serialize(src.ContactKey)));

I think that would prevent the error you're getting.

Community
  • 1
  • 1
Tim S.
  • 55,448
  • 7
  • 96
  • 122
1

AutoMapper is complaining that you don't have a default constructor because AutoMapper needs to create an empty instance of the target class before it can map values to it. It can't call your ContractKey's parameterized constructor - how would it?

In this case it might seem simple, if the constructor looks like this:

public ContracktKey(string keyValue){}

But what if it had two parameters?

public ContracktKey(string keyValue, string otherValue){}

How would it know where to put the value? What if you only provided one string?

I think it would be best to follow others' advice and map the two TicketFlag objects.

SouthShoreAK
  • 4,176
  • 2
  • 26
  • 48
  • I understand why it needs a default ctor. In this case, it makes no sense to even try and call it (and I don't want a default ctor to provide for callers, they really need to be using the parameterized one). You're correct - I should be using the other's answers. Good explanation. – Nicolas Webb Sep 26 '13 at 20:34