-
-
Notifications
You must be signed in to change notification settings - Fork 3
Instance Providers
The InstanceProvider
class provides a way to control how instances of a row are obtained during deserialization. InstanceProviders
are only used during static deserialization.
InstanceProvider
instances can be backed by constructors, methods, and delegates.
Delegates and methods return a bool
value where true
indicates success and false
indicates failure. If a delegate or method fails and a fallback has been configured with Else(InstanceProvider)
the fallback will be tried.
Two kinds of constructors are supported, those taking zero parameters and those taking some set of parameters that have corresponding Setters
.
You can create an InstanceProvider
backed by a zero parameter constructor with the InstanceProvider.ForParameterlessConstructor(ConstructorInfo)
method.
You can create an InstanceProvider
backed by a constructor taking parameters with the InstanceProvider.ForConstructorWithParameters(ConstructorInfo)
method. InstanceProvider
of this kind will not be invoked until all values are available for the corresponding setters, and row reuse is not supported.
Constructors are assumed to never fail, and therefore will never fallback to another InstanceProvider
. If a constructor is fallible, it should be wrapped in a method or delegate that detects failures and returns false
.
Any delegate of the form bool Name(in ReadContext, out DesiredType)
can back an InstanceProvider
.
Cesil provides InstanceProviderDelegate<TInstance>
and DynamicRowConverter.ForDelegate<TInstance>(InstanceProviderDelegate<TInstance>)
which conform to this form. You can also explicitly cast any delegate to InstanceProvider
, provided it is logically equivalent to InstanceProviderDelegate<TInstance>
.
If a delegate backed InstanceProvider
returns false
, the InstanceProvider
configured by Else(InstanceProvider)
(if any) will be tried next.
Any static MethodInfo
that exposes the same interface as InstanceProviderDelegate<TInstance>
can back an InstanceProvider
.
Concretely, the method must:
- be static
- return a
bool
- have 2 parameters
- The first parameter must be
in ReadContext
- The second parameter must be an
out
parameter of the desired type
- The first parameter must be
Use the InstanceProvider.ForMethod(MethodInfo)
method to create a InstanceProvider
backed by a method. You can also explicitly cast any MethodInfo
to InstanceProvider
, provided it is logically equivalent to InstanceProviderDelegate<TInstance>
.
If a method backed InstanceProvider
returns false
, the InstanceProvider
configured by Else(InstanceProvider)
(if any) will be tried next.
For convenience, InstanceProvider
has a GetDefault(TypeInfo)
method which will return an InstanceProvider
for any of the following:
- All value types, the returned provider will create the default value
- Reference types with a public zero parameter constructors, the returned provider will invoke the zero parameter constructor
-
string
, the returned provider will create a null value -
Version
, the returned provider will create a null value -
Uri
, the returned provider will create a null value
These default InstanceProvider
are used by the Default Type Describer to implement ITypeDescriber.GetInstanceProvider(TypeInfo)
.
Delegate and method backed InstanceProviders
can fail, and indicate that by returning false
. If Cesil cannot obtain an instance due to these failures, an exception is raised.
To try another InstanceProvider
after one fails, you chain them with the Else(InstanceProvider)
method. Else(InstanceProvider)
specifies which InstanceProvider
to try if the current one fails.
Else(InstanceProvider)
returns a new InstanceProvider
, the original is not modified.
If a InstanceProvider
already has a fallback InstanceProvider
specified, the one passed to Else(InstanceProvider)
will be tried after all the others have failed. Conceptually, Else(InstanceProvider)
adds a InstanceProvider
to the end of a list of fallbacks to try.
Cesil provides explicit casts MethodInfo
, ConstructorInfo
and Delegate
to InstanceProvider
. These are roughly equivalent to calling the static ForXXX(...)
methods on InstanceProvider
, but differ by allowing null
values.