Conditional mapping

Jan 27, 2010 at 6:59 PM


I have two classes with different properties names. User can choose which fields and how should be mapped. See example below.

class A
  public int Id {get;set;}
  public string Subject {get;set;}
  public string Note {get;set;}

class B
  public string Prop1 {get;set;}
  public string Prop2 {get;set;}
  public string Prop3 {get;set;}

User fill dictionary<string, string>. Pairs for example:

pairs.Add("Id", "Prop2");
pairs.Add("Subject", "Prop3");
pairs.Add("Note", "Prop1");

Also user can specify which properties should be skipped during  mapping

mapping.Add("Id", true);
mapping.Add("Subject", false);
mapping.Add("Note", true);

Can you help me how to create mapping config? I did following

class AtoBMapConfig : DefaultMapConfig
  protected override bool MatchMembers(string sourceProperty, string destProperty)
    string value;
    if(_fieldsMapping.TryGetValue(sourceProperty, out value))
      return value == destProperty;
      return false;

This config helps to solve problem with properties names. But how to take into account which properties should be skipped. I think i have to override GetMappingOperations and generate operations with delegate. But i cannot understand which operation class i should use. Who can help with example.

Thanks a lot.

Jan 27, 2010 at 7:57 PM
Edited Jan 27, 2010 at 7:59 PM


You can add an additional checking to the MatchMembers function:

var mapConfig = new DefaultMapConfig().MatchMembers((m1, m2) => pai$rs[m1] == m2 && mapping[m1]);


var mapper = ObjectMapperManager.DefaultInstance.GetMapper<Source, Destination>(mapConfig);


Also you can use "IgnoreMembers" configuration function:

Jan 28, 2010 at 9:04 AM

Thanks, and one more question about performance.
A User setups properties names mapping only one time (by app.config). But user very often change which properties should be skipped during mapping.
In your example i should create mapConfig instance every time. In this case we will generate new code every time. Am i right? I didn't test speed. But should i think about this and try to implement complex operation? Or can i forget about this and use your solution as true way?

Jan 30, 2010 at 8:08 AM

EmitMapper will not generate mappers every time - it caches them. To force the library generate new mapper when mapping should be updated use the configuration method "SetConfigName" wich has one parameter - unique mapping configuration identifier. So, when you know that mapper should be updated pass there a new string value (for example it can be a guid). Also you can store generated mapper in some variable which is accessible from different modules (for example it can be a singleton) and when user updates configuration then new mapper is generated and stored to this variable.

Jan 30, 2010 at 8:08 PM

I don't want to add caching responsibility to my code. Good hint about SetConfigName. I will use it.