-
Notifications
You must be signed in to change notification settings - Fork 1
Object Binders
Whenever a request is submitted with an entity body to the client (for example, the content of an html form, or some json values), OpenRasta will attempt to turn the entity into objects needed for an operation to succeed (by default, the parameters of a method). To do so, an object binder will be used.
Unlike other frameworks, OpenRasta’s architecture relies on codecs to do the actual parsing of the content, and delegates the object creation to the object binder. As such, just like codecs, object binders can work in two modes, object and key values processing.
Codecs implementing IMediaTypeReader
always return a fully-built object. As such, there is no matching to do on the parameter. The binder’s SetInstance
method will be called with the object created by the codec.
Codecs implementing IKeyedValuesMediaTypeReader
return a list of string keys, each of them associated with a number of values of whatever type the codec returns. The binder’s responsibility is then to locate which property to assign by matching the key, and to convert the values in objects through the ValueConverter
delegate that was passed by the codec. This is done through the SetProperty<TValue>(string key, IEnumerable<TValue> values, ValueConverter<TValue> converter)
method on the binder.
How the matching is executed is dependent on the object binder in use. Two binders are available by default, the default object binder and the changeset object binder.
Which object binder is selected for each input of an operation is decided by the class implementing the IObjectBinderLocator
interface. By default, binders get located by attributes or by method.
Binders can be created from attributes inheriting from the BinderBaseAttribute
. Such an attribute can be defined on the parameter of a method itelf, or on the type of the parameter.
public class Customer {
}
public class CustomerHandler {
public OperationResult Post([KeyedValuesBinder]Customer customer) {}
}
or
[KeyedValuesBinder]
public class Customer {
}
public class CustomerHandler {
public OperationResult Post(Customer customer) {}
}
It is not always possible to use an attribute. For those cases, the default binder locator will try and locate a GetBinder
method with no parameter on the type for which resolving is being attempted.
public class Customer {
public static IObjectBinder GetBinder(ITypeSystem typeSystem, IMember member) { /* return new object binder */ }
}