-
-
Notifications
You must be signed in to change notification settings - Fork 3
Dynamic Row Converters
The DynamicRowConverter
class provides a way to control what happens when a row read into a dynamic
variable is cast to a static type. You obtain dynamic
rows using an IReader<dynamic>
or IAsyncReader<dynamic>
created by a IBoundConfiguration<dynamic>
you made with a call to Configuration.ForDynamic(Options)
.
There is one kind of cast that will always succeed, and will not consult a DynamicRowConverter
- casts to IDisposable
. This is to allow disposal to always function appropriately, whether done explicitly with calls to IDisposable.Dispose()
or implicit with using
statements.
The Default Type Describer supports common conversions and may be adequate for your needs.
DynamicRowConverter
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(DynamicRowConverter)
the fallback will be tried.
Three kinds of constructors are supported:
- Constructors taking a single
dynamic
(or, equivalently,object
) parameter- Created with
DynamicRowConverter.ForConstructorTakingDynamic(ConstructorInfo)
- You may also explicitly cast such a
ConstructorInfo
to aDynamicRowConverter
- Created with
- Constructors taking some number of parameters, paired with a
ColumnIdentifier
set mapping columns to specific parameters - Constructors taking no parameters, paired with a
Setter
andColumnIdentifier
set mapping columns to specific setters
Constructors are assumed to never fail, and therefore will never fallback to another DynamicRowConverter
. 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(object, in ReadContext, out DesiredType)
can back a DynamicRowConverter
.
Cesil provides DynamicRowConverterDelegate<TOutput>
and DynamicRowConverter.ForDelegate<TOutput>(DynamicRowConverterDelegate<TOutput>)
which conform to this form. You can also explicitly cast any delegate to DynamicRowConverter
, provided it is logically equivalent to DynamicRowConverterDelegate<TOutput>
.
If a delegate backed DynamicRowConverter
returns false
, the DynamicRowConverter
configured by Else(DynamicRowConverter)
(if any) will be tried next.
Any static MethodInfo
that exposes the same interface as DynamicRowConverterDelegate<TOutput>
can back a DynamicRowConverter
.
Concretely, the method must:
- be static
- return a
bool
- have 3 parameters
- The first parameter must be
dynamic
orobject
- The second parameter must be
in ReadContext
- The third parameter must be an
out
parameter of the desired type
- The first parameter must be
If a method backed DynamicRowConverter
returns false
, the DynamicRowConverter
configured by Else(DynamicRowConverter)
(if any) will be tried next.
Delegate and method backed DynamicRowConverters
can fail, and indicate that by returning false
. If Cesil cannot convert a row due to these failures, an exception will be raised.
To try another DynamicRowConverter
after one fails, you chain them with the Else(DynamicRowConverter)
method. Else(DynamicRowConverter)
specifies which DynamicRowConverter
to try if the current one fails.
Else(DynamicRowConverter)
returns a new DynamicRowConverter
, the original is not modified.
If a DynamicRowConverter
already has a fallback DynamicRowConverter
specified, the one passed to Else(DynamicRowConverter)
will be tried after all the others have failed. Conceptually, Else(DynamicRowConverter)
adds a DynamicRowConverter
to the end of a list of fallbacks to try.
Cesil provides explicit casts from ConstructorInfo
, MethodInfo
, and Delegate
to DynamicRowConverter
. These are roughly equivalent to calling the static ForXXX(...)
methods on DynamicRowConverter
, but differ in a few ways.
For all explicit casts, unlike the ForXXX(...)
methods, null
values are allowed (returning null
themselves).
The ConstructorInfo
explicit cast only accepts constructors that accept a single object
or dynamic
parameter, other types of constructors must use the appropriate ForXXX(...)
methods.
The Delegate
explicit cast accepts non-DynamicRowConverterDelegate<TOutput>
delegates, unlike the DynamicRowConverter.ForDelegate<TOutput>(DynamicRowConverterDelegate<TOutput>)
method.