Skip to content

Object Mapping

Ricardo Diaz edited this page Aug 8, 2017 · 1 revision

These are the topics you'll find covered on this page:

Introduction

Often you want to transfer member values from one object to another, whether of the same or of different types. The mapping facilities in Fasterflect allow you to do this with a single operation that will generate just a single dynamic method to transfer all member values. This makes the object mapping facilities in Fasterflect very fast when compared to the alternatives provided elsewhere.

All mappings require members to have the same name in the source and target. By default, case is respected when mapping from members of the same type (such as properties to properties ) and ignored when mapping between members of different types. Case is also respected when mapping both fields and properties (on both source and target), but ignored if mapping both to just one of the two.

If you need more advanced mapping functionality than provided here you should check out AutoMapper, which provides greater flexibility and additional features.

Mapping object members

The core functionality is provided by the Map method shown below, which exposes all of the supported parameters.

void Map( this object source, object target, MemberTypes sourceTypes, MemberTypes targetTypes, Flags bindingFlags, params string[] names );

The following illustrates how this method might be used to copy member values between objects:

// example showing how one might use the Map method
var source = new { ID=42, Name="Arthur Dent" };
var target = new Person();
// maps all members (ignoring case as sourceMemberTypes != targetMemberTypes)
source.Map( target, MemberTypes.Properties, MemberTypes.Fields, Flags.InstanceAnyVisibility );
// maps selected members (respecting case as sourceMemberTypes == targetMemberTypes)
source.Map( target, MemberTypes.Properties, MemberTypes.Properties, Flags.InstanceAnyVisibility, "ID", "Name" );
// maps all members (ignoring case as sourceMemberTypes != targetMemberTypes)
source.Map( target, MemberTypes.Properties, MemberTypes.Fields | MemberTypes.Properties, Flags.InstanceAnyVisibility );

// the special case of using an anonymous source for which no variable has been declared can look odd
new { ID=42, Name="Arthur Dent" }.Map( target, MemberTypes.Properties, MemberTypes.Fields, Flags.InstanceAnyVisibility );
// this can be made more readable by calling the extension method the old-fashioned way
MapExtensions.Map( new { ID=42, Name="Arthur Dent" }, target, MemberTypes.Properties, MemberTypes.Fields, Flags.InstanceAnyVisibility );

In case you don't care about the member types (as long as the names match up) you can use one of the following overloads, which will include both fields and properties and match the names (if any are supplied) case-sensitively.

void Map( this object source, object target, Flags bindingFlags, params string[] names );
void Map( this object source, object target, params string[] names );

Speedup the process with Delegate API

Delegate API is available for object mapping too! Use the following extension methods to access to the mapping delegates.

public static ObjectMapper DelegateForMap(this Type sourceType, Type targetType, params string[] names);
public static ObjectMapper DelegateForMap(this Type sourceType, Type targetType, Flags bindingFlags, params string[] names);
public static ObjectMapper DelegateForMap(this Type sourceType, Type targetType, MemberTypes sourceTypes, MemberTypes targetTypes, Flags bindingFlags, params string[] names);

Convenience methods for common scenarios

In addition to the above Fasterflect provides companion methods to cover the four possible combinations of mapping between fields and properties. Using these methods makes your code more explicit about what is going on which is generally considered good practice.

// maps fields to fields (respecting case)
void MapFields( this object source, object target, params string[] names );
// maps fields to properties (ignoring case)
void MapFieldsToProperties( this object source, object target, params string[] names );
// maps properties to properties (respecting case)
void MapProperties( this object source, object target, params string[] names );
// maps properties to fields (ignoring case)
void MapPropertiesToFields( this object source, object target, params string[] names );

Given the self-explanatory nature of these methods we are confident that no further explanations or examples are necessary, but if you disagree please don't hesitate to let us know.