Have following code
public delegate object ParseHandler(string s);
public static ParseHandler GetParser(Type t)
{
MethodInfo parse = t.GetMethod("Parse", BindingFlags.Static | BindingFlags.Public,
null, new Type[] { typeof(string) }, null);
if (parse != null)
return (ParseHandler)Delegate.CreateDelegate(typeof(ParseHandler), parse, true);
return null;
}
is blowing up on the Delegate.CreateDelegate()
call with "Error binding to target method." apparently because ParseHandler
is defined as returning object
instead of type specific return value.
I don't know type at the compile type, so I can't replace type
parameter with generic (and if I did then the whole function would not be needed).
A bit confused on how to deal with this. The required behavior is to find public static Parse(string)
method for given type and create a delegate for it to be called later.
It should be fine so long as the real return value is a reference type - but it makes sense for this to fail for a value type return value. (See Eric Lippert's post about representation and identity for more detailed explanations.)
One option is to create a generic class like this:
public class BoxingParserDelegate<T>
{
private readonly Converter<string, T> parser;
public BoxingParserDelegate(Converter<string, T> parser)
{
this.parser = parser;
}
public object Parse(string x)
{
return parser(x);
}
}
In your GetParser method, you'd check whether the return type of parse
is a value type, and if so create an instance of BoxingParserDelegate<T>
via reflection. You can then create the ParseHandler
instance from the Parse method of the BoxingParserDelegate
.
This will all be frankly somewhat awkward, but should work. It feels like there should be a simpler approach, to be honest.
(On .NET 3.5 or higher I'd recommend using expression trees, but I've only just seen the .NET 2.0 tag.)
EDIT: Aha, have thought of slightly simpler approach:
public static ParseHandler BuildParseHandler<T>(Converter<string, T> converter)
{
// Performs boxing automatically
return delegate(string x) { return converter(x); }
}
This is effectively asking the compiler to do half of the above work for you. Then you just need to work out whether you need to call this, and do so with reflection if necessary. Something like this:
public static ParseHandler GetParser(Type t)
{
MethodInfo parse = t.GetMethod("Parse",
BindingFlags.Static | BindingFlags.Public,
null, new Type[] { typeof(string) }, null);
// Method not found
if (parse == null)
{
return null;
}
// Reference type - use delegate covariance
if (!parse.ReturnType.IsValueType)
{
return (ParseHandler) Delegate.CreateDelegate(typeof(ParseHandler),
parse, true);
}
// Tricky situation: call BuildParseHandler with generics
Type delegateType = typeof(Converter<,>).MakeGenericType(typeof(string),
parse.ReturnType);
object converter = Delegate.CreateDelegate(delegateType, parse, true);
// You may need extra work to get this... let me know whether or not it works.
// Obviously if you make it private, you'll need extra binding flags.
MethodInfo method = typeof(TypeContainingThisMethod)
.GetMethod("BuildParseHandler");
method = method.MakeGenericMethod(parse.ReturnType);
return (ParseHandler) method.Invoke(null, new object[] { converter });
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.