in Elastic.SemanticKernel.Connectors.Elasticsearch/Internal/Helpers/VectorStoreRecordMapping.cs [107:185]
public static object? CreateEnumerable<T>(IEnumerable<T> input, Type requiredEnumerable)
{
if (input is null)
{
return null;
}
// If the required type is an array, we can create an ArrayList of the required type, add all
// items from the input, and then convert the ArrayList to an array of the required type.
if (requiredEnumerable.IsArray)
{
if (requiredEnumerable.HasElementType)
{
var elementType = requiredEnumerable.GetElementType();
var arrayList = new ArrayList();
foreach (var item in input)
{
arrayList.Add(item);
}
return arrayList.ToArray(elementType!);
}
return input.ToArray();
}
// If the required type is one of a few supported generic collection interface types that
// are all implemented by List<>, we can create a LIst<> and add all items from the input.
if (requiredEnumerable.IsGenericType)
{
var genericTypeDefinition = requiredEnumerable.GetGenericTypeDefinition();
if (genericTypeDefinition == typeof(ICollection<>) ||
genericTypeDefinition == typeof(IEnumerable<>) ||
genericTypeDefinition == typeof(IList<>) ||
genericTypeDefinition == typeof(IReadOnlyCollection<>) ||
genericTypeDefinition == typeof(IReadOnlyList<>))
{
// Create a List<> using the generic type argument of the required enumerable.
var genericMemberType = requiredEnumerable.GetGenericArguments()[0];
var listType = typeof(List<>).MakeGenericType(genericMemberType);
var enumerableType = typeof(IEnumerable<>).MakeGenericType(genericMemberType);
var constructor = listType.GetConstructor([]);
var list = (IList)constructor!.Invoke(null);
// Add all items from the input into the new list.
foreach (var item in input)
{
list.Add(item);
}
return list;
}
}
// If the required type is IEnumerable, we can return the input as is.
if (requiredEnumerable == typeof(IEnumerable))
{
return input;
}
// If our required type implements IList and has a public parameterless constructor, we can
// create an instance of it using reflection and add all items from the input.
if (typeof(IList).IsAssignableFrom(requiredEnumerable))
{
var publicParameterlessConstructor = requiredEnumerable.GetConstructor([]);
if (publicParameterlessConstructor is not null)
{
// Create the required type using the parameterless constructor and cast
// it to an IList so we can add our input items.
var list = (IList)publicParameterlessConstructor.Invoke(null);
foreach (var item in input)
{
list.Add(item);
}
return list;
}
}
throw new NotSupportedException($"Type {requiredEnumerable.FullName} is not supported.");
}