所以几天后我想通了。首先,我将 2 个 IDataviews 转换为在运行时获取类型的 IEnumerable。之后,我通过将它们转换为列表来将它们合并在一起,并使用反射将它们转换为正确的类型。最后我再次使用反射将最终的可枚举加载回 IDataview。
var oldDataEnumerable = GetDataEnumerable(mlContext, oldDataView, dataViewType).ToList();
var newDataEnumerable = GetDataEnumerable(mlContext, newDataView, dataViewType).ToList();
var mergedEnumerable = MergeDataEnumerables(oldDataEnumerable, newDataEnumerable, dataViewType);
return LoadEnumerableFromObject(mlContext, mergedEnumerable, dataViewType);
private IEnumerable<object> GetDataEnumerable(MLContext mlContext, IDataView dataView, Type dataViewType) {
var createEnumerableMethod = typeof(DataOperationsCatalog).GetMethod(nameof(MLContext.Data.CreateEnumerable));
var generic = createEnumerableMethod.MakeGenericMethod(dataViewType);
return (IEnumerable<object>)generic.Invoke(mlContext.Data, new object[] { dataView, false, null, null });
}
private object MergeDataEnumerables(List<object> firstDataEnumerable, List<object> secondDataEnumerable, Type dataViewType) {
firstDataEnumerable.AddRange(secondDataEnumerable);
var castMethod = typeof(Enumerable).GetMethod("Cast");
var genericCast = castMethod.MakeGenericMethod(dataViewType);
var toListMethod = typeof(Enumerable).GetMethod("ToList");
var genericToList = toListMethod.MakeGenericMethod(dataViewType);
var castedEnumerable = genericCast.Invoke(null, new[] { firstDataEnumerable });
return genericToList.Invoke(null, new[] { castedEnumerable });
}
private IDataView LoadEnumerableFromObject(MLContext mlContext, object dataEnumerable, Type dataViewType) {
var dataType = mlContext.Data.GetType();
var loadFromEnumerableMethod = dataType.GetMethods().First(m => m.Name == "LoadFromEnumerable" && m.IsGenericMethod);
var generic = loadFromEnumerableMethod.MakeGenericMethod(dataViewType);
var schema = SchemaDefinition.Create(dataViewType);
return (IDataView)generic.Invoke(mlContext.Data, new object[] { dataEnumerable, schema });
}