좋아, 그래서 난 그냥 본질적으로 수동 유형 유추입니다 코딩, 그리고 내가 원하는 걸해야한다고 생각합니다.
public static class TypeExtensions {
public static Type GetTypeDefinition (this Type type) {
return type.IsGenericType ? type.GetGenericTypeDefinition() : type;
}
public static IEnumerable<Type> GetImproperComposingTypes (this Type type) {
yield return type.GetTypeDefinition();
if (type.IsGenericType) {
foreach (var argumentType in type.GetGenericArguments()) {
foreach (var t in argumentType.GetImproperComposingTypes()) yield return t;
}
}
}
private static Dictionary<Type , Type> GetInferenceMap (ParameterInfo[] parameters , Type[] types) {
var genericArgumentsMap = new Dictionary<Type , Type>();
var match = parameters.All (parameter => parameter.ParameterType.GetImproperComposingTypes().Zip (types[parameter.Position].GetImproperComposingTypes()).All (a => {
if (!a.Item1.IsGenericParameter) return a.Item1 == a.Item2;
if (genericArgumentsMap.ContainsKey (a.Item1)) return genericArgumentsMap[a.Item1] == a.Item2;
genericArgumentsMap[a.Item1] = a.Item2;
return true;
}));
return match ? genericArgumentsMap : null;
}
public static MethodInfo MakeGenericMethod (this Type type , string name , Type[] types) {
var methods = from method in type.GetMethods()
where method.Name == name
let parameters = method.GetParameters()
where parameters.Length == types.Length
let genericArgumentsMap = GetInferenceMap (parameters , types)
where genericArgumentsMap != null
where method.GetGenericArguments().Length == genericArgumentsMap.Keys.Count()
select new {
method ,
genericArgumentsMap
};
return methods.Select (m => m.method.IsGenericMethodDefinition ? m.method.MakeGenericMethod (m.method.GetGenericArguments().Map (m.genericArgumentsMap).ToArray()) : m.method).SingleOrDefault();
}
}
은 그래서
public class Foos {
public void Foo<T1 , T2 , T3> (int a , T1 b , IEnumerable<T2> c , Expression<Func<T1 , T3 , string>> d) {
}
public void Foo<T1 , T2 , T3> (int a , T1 b , IEnumerable<T2> c , Expression<Func<T1 , T3 , int>> d) {
}
public void Foo() {
}
public void Foo (string s) {
}
}
은 내가 원하는 방법을 선택할 수 있습니다 제공 :
var method = typeof (Foos).MakeGenericMethod ("Foo" , new[] { typeof (int) , typeof (DateTime) , typeof (IEnumerable<string>) , typeof (Expression<Func<DateTime , double , int>>) });
method.Invoke (new Foos() , new object[] { 1 , DateTime.Now , null , null });
var method = typeof (Foos).MakeGenericMethod ("Foo" , Type.EmptyTypes);
method.Invoke (new Foos() , new object[] { });
var method = typeof (Foos).MakeGenericMethod ("Foo" , new[] { typeof (string) });
method.Invoke (new Foos() , new object[] { "zozo" });
이 아닌 일반적인 방법을 지원하는 것,하지만 분명히 (명시 적으로 일반적인 인수를 지원하지 않습니다), 그리고 아마도 약간의 작업이 필요하지만, 그 핵심입니다.