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));
}