The mapping configuration for a specific type can be defined as a method in any class.
public class FluentRules
{
public void Map(ITypeMappingConfigurator<Customer> map)
{
map.Exclude(x => x.Password);
map.Include(x => x.Name);
map.Include(x => x.Identifier, o => o.AsPrimaryKey());
}
}
Any object containing fluent rules must be returned from the FluentRuleObjects
property of your configuration class to be considered:
Pomona will scan fluent rule objects and look for methods taking one argument
of type ITypeMappingConfigurator<T>
. A rule methods will be applied to T
and all subtypes of T
.
public class Configuration : PomonaConfigurationBase
{
public override IEnumerable<object> FluentRuleObjects
{
get { yield return new FluentRules();}
}
}
Type options
Type options are defined through the ITypeMappingConfigurator<T>
interface.
Rules specified using ITypeMappingConfigurator<T>
can either be chained, or split
up in multiple declarations.
Ignoring properties
A property can be ignored and hidden from the exposed resource by using the Exclude
method.
public void ExcludeRule(ITypeMappingConfigurator<Customer> customer)
{
customer.Exclude(x => x.Password);
}
Selecting handler
A handler class can be chosen for a resource type by using the HandledBy<T>
method.
public void HandlerRule(ITypeMappingConfigurator<Customer> customer)
{
customer.HandledBy<CustomerHandler>();
}
You can find out more about this in Resource handlers
Treating type as a value object
We can treat a complex type as a value object, as opposed to a resource. A value object can be a part of resource or another value object, and has no URI.
public void ValueObjectRule(ITypeMappingConfigurator<Customer> customer)
{
customer.AsValueObject();
}
You can learn more about value types in Contributors guide
Custom construction of object
When Pomona needs to instantiate a resource or value object type during deserialization, it uses the empty constructor by default if available.
If we want to instantiate the object using a non-empty constructor or a method taking parameters,
we can use the ConstructedUsing
method.
public void ConstructedUsingRule(ITypeMappingConfigurator<Customer> customer)
{
customer.ConstructedUsing(c => new Customer(c.Requires().Name, c.Optional().Password));
}
The ConstructedUsing
method accepts an Expression<Func<IConstructorControl<TDeclaringType>, TDeclaringType>>
argument.
The IConstructorControl<T>
parameter can then be used to bind properties with
any corresponding parameters.
Constructor context
If we need to access some service while instantiating a type we can use the Context<T>()
method of IConstructorControl<T>
.
public void ContextfulConstructionRule(ITypeMappingConfigurator<Customer> customer)
{
customer.ConstructedUsing(
c => c.Context<ICustomerFactory>()
.CreateCustomer(c.Requires().Name, c.Optional().Password));
}
Specifying plural name of type
Pomona will try to derive the plural name of a type by using a few simple rules, which works for a majority of English words.
This value is used to generate the URI for a root resource collection type.
public void PluralNameRule(ITypeMappingConfigurator<Mouse> mouse)
{
mouse.WithPluralName("Mice");
}
Property options
We can change how a property will be exposed by using the Include
method of
ITypeMappingConfigurator
with an options
lambda argument specified.
Changing exposed name of property
To use a different name for a property when exposed you can use Named
method.
public void IncludePropertyNamed(ITypeMappingConfigurator<Customer> customer)
{
customer.Include(x => x.Identifier, x => x.Named("Id"));
}
Using custom accessors
By using the following methods we can change how a property is accessed.
OnGet
: Used when serializing from resourceOnSet
: Used when deserializing to resourceOnQuery
: For building LINQ queries, usually for properties not recognized by underlying LINQ provider
public void IncludePropertyWithCustomAccessors(ITypeMappingConfigurator<Customer> customer)
{
customer
.Include(x => x.Name, x => x
.OnGet(y => y.Name.ToUpper())
.OnSet((c, v) => c.Name = v.ToLower())
.OnQuery(y => y.Name.ToUpper()));
}
Expand
We can use Expand
to configure whether, and how, resource(s) referenced by properties are
included when serializing. It takes one parameter of type ExpandMode
, which can have the
following values:
ExpandMode.Full
: For properties pointing to a single resource, it means expand that resource. For properties having a list of resources this means expand the list itself and every item.ExpandMode.Shallow
: Expands as list of references to resources. Only applicable to properties having a collection of resources.
public void ExpandProperty(ITypeMappingConfigurator<Customer> customer)
{
customer
.Include(x => x.Address, x => x.Expand(ExpandMode.Full));
}