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. 🙂