Yesterday I presented a problem that I struggle with for several hours: given a generic Func<T,object> created by a fluent DSL, how can I call a method that only accepts a non-generic Func<object,object>? The answer is actually quite simple.
Here’s the relevant non-compiling code from yesterday:
internal interface ISerializationConfig
{
...
void SerializePropertyAsElementUsing(Type target,
PropertyInfo property,
string elementName,
Func<object, object> converter);
}
...
ITypeSerializationSpec<T> IInitialPropertySerializationSpec<T>.Using(Func<T, object> selector)
{
//_config is of type ISerializationConfig.
_config.SerializePropertyAsElementUsing(typeof(T),
_expression.GetProperty(),
_expression.GetProperty().Name,
/*ERROR:*/ selector);
return this;
}
...
The answer is actually so simple that I felt dumb for not seeing it immediately. We can wrap our generic Func<T,object> inside a non-generic Func<object,object>. The wrapper Func basically serves as an adapter, enabling us to pass an instance of one type to a method that only accepts an instance of another type:
ITypeSerializationSpec<T> IInitialPropertySerializationSpec<T>.Using(Func<T, object> selector)
{
Func<object,object> wrapper = o => selector((T)o);
//_config is of type ISerializationConfig.
_config.SerializePropertyAsElementUsing(typeof(T),
_expression.GetProperty(),
_expression.GetProperty().Name,
/* This works! */wrapper);
return this;
}
I love it when there is a simple and elegant solution to a seemingly complex and nasty problem. :)
Tags: