Skip to content

Complexes

Leonardo Porro edited this page Feb 12, 2023 · 23 revisions

A complex is a type that contains a set of members and a constructor. It is usually a .NET class but it extends to any other structure that can represent a set of name->value pairs (i.e.: members, properties), such as:

  • Anonymous classes, are handled just as regular ones.
  • Dictionary<string, object>, each key-pair value represents a member,
  • JsonObject where each value node represents a member.
  • Any other custom type that can hold a set of member _name _-> value pairs.

Complexes can be seen as an abstraction of a regular object, and they can be extended to handle custom types.

Configuration

Customize constructor

Specify an expression used to build a new instance.

Fluent configuration
services.AddDbContext<MainDbContext>(dbContextOptions =>
{
   ...
   dbContextOptions.UseMapping(mappingOptions => {
      mappingOptions.Default(profileOptions => {
          profileOptions.Type<Invoice>().Constructor(c => new Invoice(1));
      });
   });
});

Members

Members are variables associated with the complex type. They can be represented by propertes for .NET classes, key-value pairs (for Dictionary<string, object>) or any other slot that can contain named values for custom types.

Accessors

Members have getter and setter in order to allow the mapper to read and write values. Different types have different ways to access its values, for example:

  • .NET Clr class has properties and the accessors are the getter and setter of the property
  • Dictionary<string, object> has entries and the accessor is the indexer [] or the TryGetValue / Add methods.

Configuration

Members can be renamed, ignored, removed and custom code may be added to getters and setters, also they can hold annotations.

Exclude members (Type)

Ignore the specified members in all map operation for the any type combination.

Annotated configuration
public class TargetEntity
{
   public string Text1 { get; set; }

   [NotMapped]
   public string Text2 { get; set; }
}
Fluent configuration
services.AddDbContext<MainDbContext>(dbContextOptions =>
{
   ...
   dbContextOptions.UseMapping(mappingOptions => {
      mappingOptions.Default(profileOptions => {
         profileOptions.Type<TargetEntity>().Member(m => m.Text2).Exclude();
      });
   });
});

Exclude members (Map)

Ignore the specified members in all map operations for the given type combination.

Fluent configuration
services.AddDbContext<MainDbContext>(dbContextOptions =>
{
   dbContextOptions.UseMapping(mappingOptions => {
      mappingOptions.Default(profileOptions => {
         profileOptions.Type<Invoice>().FromType<InvoiceDTO>().Member(m => m.InvoiceType).Exclude();
      });
   });
});

Member computed value

Map a member from an arbitrary expression, including one or more different members of different types.

Fluent configuration
services.AddDbContext<MainDbContext>(dbContextOptions =>
{
   dbContextOptions.UseMapping(mappingOptions => {
      mappingOptions.Default(profileOptions => {
         profileOptions.Type<User>().FromType<UserDTO>()
                       .Member(u => u.Id).FromValue(u => u.Key + "_id");
      });
   });
});

Member source

Map a member from anorher member (i.e.: map to a different member name).

Fluent configuration
services.AddDbContext<MainDbContext>(dbContextOptions =>
{
   dbContextOptions.UseMapping(mappingOptions => {
      mappingOptions.Default(profileOptions => {
         profileOptions.Type<User>()
                       .FromType<UserDTO>()
                       .Member(u => u.Id).FromMember(u => u.Key);
      });
   });
});

Customize accessors

Custom code can be executed when getting source values or setting target values in a map operation.

Fluent configuration
services.AddDbContext<MainDbContext>(dbContextOptions =>
{
   dbContextOptions.UseMapping(mappingOptions => {
      mappingOptions.Default(profileOptions => {
         profileOptions.Type<TargetEntity>()
                       .Member(m => m.Value)
                       .Setter((@this, value, mapContext) =>
                       {
                          @this.Value = value + 1;
                       });

          profileOptions.Type<SourceEntity>()
                        .Member(m => m.Value)
                        .Getter((@this, mapContext) =>
                        {
                           return @this.Value + 1;
                         });
      });
   });
});