/// <summary>
/// Will fetch first occurence of IEnumerable<T> method and generate new generic method
/// <para/>
/// that corresponds to Document type
/// </summary>
/// <param name="Document"></param>
/// <param name="MethodName"></param>
/// <returns></returns>
public static MethodInfo GetAppropriateCollectionGenericMethod(object SourceClass, dynamic Document, string MethodName)
{
//get all public methods
var publicMethods = SourceClass.GetType().GetMethods().Where(x => x.Name == MethodName && x.IsGenericMethod);
//filter out only useful methods
foreach (var goodMethod in publicMethods)
{
var methodParams = goodMethod.GetParameters();
var firstParameterType = methodParams[0].ParameterType;
//methods that has arguments like Ienumerable<T>, RepeatedField<T> and so on
var hasNested = firstParameterType.GenericTypeArguments.Length > 0;
if (hasNested == true)
{
//if we found first method with that name that has as parameter an IEnumerable<T> we are ok
var genericTypeDef = firstParameterType.GetGenericTypeDefinition();
if (genericTypeDef == typeof(IEnumerable<>))
{
//Recover current document type, even if it's a list of such types
Type documentType = GetDocumentNestedType(Document);
//simply create a generic method based on Document inner Type
return goodMethod.MakeGenericMethod(documentType);
}
}
}
return null;
}
您将需要这个,以避免错误:
var hasNested = firstParameterType.GenericTypeArguments.Length > 0;
这将获取第一次出现的:
public static void m<T>(IEnumerable<T> Ls)
{
}
并将生成一个您可以使用的方法:
var localMethod = GenericReflectionHelper.GetAppropriateCollectionGenericMethod(this, Document, nameof(Insert));
//we are relying on implicit casting
localMethod.Invoke(this, new object[] { Document });
完整样本:
public void Insert<T>(T Document)
{
//Valid for Lists and Repeated Fields
if (Document is IEnumerable)
{
MethodInfo localMethod;
var tuple = Tuple.Create(Document.GetType(), nameof(Insert));
if (CachedMethodsRedirection.ContainsKey(tuple) == true)
{
localMethod = CachedMethodsRedirection[tuple];
}
else
{
localMethod = GenericReflectionHelper.GetAppropriateCollectionGenericMethod(this, Document, nameof(Insert));
CachedMethodsRedirection.Add(tuple, localMethod);
}
//we are relying on implicit casting
localMethod.Invoke(this, new object[] { Document });
}
else
{
DocumentSession.GetCollection<T>().Insert(Document);
}
}
public void Insert<T>(IEnumerable<T> Document)
{
DocumentSession.GetCollection<T>().Insert(Document);
}