Все должно быть в порядке, если реальное возвращаемое значение является ссылочным типом, но имеет смысл, что это не удастся для возвращаемого значения типа значения. (См. Сообщение Эрика Липперта о представлении и идентичности для более подробных объяснений.)
Один из вариантов - создать универсальный класс, подобный этому:
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);
}
}
В вашем методе GetParser вы проверяете, является ли тип возвращаемого значения parse
типом значения, и, если это так, создаете экземпляр BoxingParserDelegate<T>
с помощью отражения. Затем вы можете создать экземпляр ParseHandler
из метода Parse BoxingParserDelegate
.
Все это будет откровенно несколько неловко, но должно сработать. Чувствуется, что должен быть более простой подход, если честно.
(На .NET 3.5 или выше я бы рекомендовал использовать деревья выражений, но я только что видел тег .NET 2.0.)
РЕДАКТИРОВАТЬ: Ага, подумал о несколько более простой подход:
public static ParseHandler BuildParseHandler<T>(Converter<string, T> converter)
{
// Performs boxing automatically
return delegate(string x) { return converter(x); }
}
Это фактически , требующий, чтобы компилятор выполнил для вас половину вышеуказанной работы. Тогда вам просто нужно выяснить, нужно ли вам это называть, и, если необходимо, сделать это с отражением. Примерно так:
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 });
}