Reflection Get List<> from List<T>(来自通用容器类型的容器类型)
Reflection Get List<> from List<T> (Container type from generic container type)
我有一个特殊的情况,在一个反射器中我可以获得不同类型的容器,我需要重新充气(比如克隆)。这种情况在引入新型容器时开始发生 (ObservableCollection<T>
)
在克隆机制中我发现的是:
if (property.PropertyType.FullName.Contains(ReflectorResources.ListName) || property.PropertyType.FullName.Contains("ConcurrentBag"))
{
var listElementType = property.PropertyType.GenericTypeArguments[0];
var newList = (property.PropertyType.FullName.Contains(ReflectorResources.IncidentListName))
? Activator.CreateInstance(typeof(Definitions.Session.Products.Motor.IncidentList<>).MakeGenericType(listElementType))
: property.PropertyType.FullName.Contains("ConcurrentBag") ? Activator.CreateInstance(typeof(ConcurrentBag<>).MakeGenericType(listElementType)) : Activator.CreateInstance(typeof(List<>).MakeGenericType(listElementType));
var oneItem = Activator.CreateInstance(listElementType);
}
所以我试着重写它:
if (new[] { ".Collections." }.Any(o => property.PropertyType.FullName.Contains(o)))
{
var listElementType = property.PropertyType.GenericTypeArguments[0];
var listType = property.PropertyType;
var constructedListType = listType.MakeGenericType(listElementType);
var newList = Activator.CreateInstance(constructedListType);
var oneItem = Activator.CreateInstance(listElementType);
}
但是它在线上爆炸了:var constructedListType = listType.MakeGenericType(listElementType);
错误
System.InvalidOperationException : Method may only be called on a Type for which Type.IsGenericParameter is true.
我的猜测是我需要从 List<Something>
...
中提取 List<>
类型
如何从通用容器类型获取容器类型?
我将引用 this answer,这可能会回答您关于反射和泛型的任何问题:
To get the unbound type from a constructed type at runtime, you can
use the Type.GetGenericTypeDefinition
method.
Type listOfInt = typeof(List<int>);
Type list = listOfInt.GetGenericTypeDefinition(); // == typeof(List<>)
而不是这个:
var listElementType = property.PropertyType.GenericTypeArguments[0];
var listType = property.PropertyType;
var constructedListType = listType.MakeGenericType(listElementType);
试试这个:
Type listElementType = property.PropertyType.GenericTypeArguments[0];
Type constructedListType;
if (! property.PropertyType.IsGenericTypeDefinition)
constructedListType = property.PropertyType;
else
{
// Depending on where your property comes from
// This should not work in the case the property type is List<T>
// How listElementType should allow you to instantiate your type ?
var listType = property.PropertyType.GetGenericTypeDefinition();
constructedListType = listType.MakeGenericType(listElementType);
}
我也是说你应该看看GetGenericTypeDefinition()
方法,但是在我写完之前已经有AakashM的答案了
那你应该看看他的回答
我有一个特殊的情况,在一个反射器中我可以获得不同类型的容器,我需要重新充气(比如克隆)。这种情况在引入新型容器时开始发生 (ObservableCollection<T>
)
在克隆机制中我发现的是:
if (property.PropertyType.FullName.Contains(ReflectorResources.ListName) || property.PropertyType.FullName.Contains("ConcurrentBag"))
{
var listElementType = property.PropertyType.GenericTypeArguments[0];
var newList = (property.PropertyType.FullName.Contains(ReflectorResources.IncidentListName))
? Activator.CreateInstance(typeof(Definitions.Session.Products.Motor.IncidentList<>).MakeGenericType(listElementType))
: property.PropertyType.FullName.Contains("ConcurrentBag") ? Activator.CreateInstance(typeof(ConcurrentBag<>).MakeGenericType(listElementType)) : Activator.CreateInstance(typeof(List<>).MakeGenericType(listElementType));
var oneItem = Activator.CreateInstance(listElementType);
}
所以我试着重写它:
if (new[] { ".Collections." }.Any(o => property.PropertyType.FullName.Contains(o)))
{
var listElementType = property.PropertyType.GenericTypeArguments[0];
var listType = property.PropertyType;
var constructedListType = listType.MakeGenericType(listElementType);
var newList = Activator.CreateInstance(constructedListType);
var oneItem = Activator.CreateInstance(listElementType);
}
但是它在线上爆炸了:var constructedListType = listType.MakeGenericType(listElementType);
错误
System.InvalidOperationException : Method may only be called on a Type for which Type.IsGenericParameter is true.
我的猜测是我需要从 List<Something>
...
List<>
类型
如何从通用容器类型获取容器类型?
我将引用 this answer,这可能会回答您关于反射和泛型的任何问题:
To get the unbound type from a constructed type at runtime, you can use the
Type.GetGenericTypeDefinition
method.Type listOfInt = typeof(List<int>); Type list = listOfInt.GetGenericTypeDefinition(); // == typeof(List<>)
而不是这个:
var listElementType = property.PropertyType.GenericTypeArguments[0];
var listType = property.PropertyType;
var constructedListType = listType.MakeGenericType(listElementType);
试试这个:
Type listElementType = property.PropertyType.GenericTypeArguments[0];
Type constructedListType;
if (! property.PropertyType.IsGenericTypeDefinition)
constructedListType = property.PropertyType;
else
{
// Depending on where your property comes from
// This should not work in the case the property type is List<T>
// How listElementType should allow you to instantiate your type ?
var listType = property.PropertyType.GetGenericTypeDefinition();
constructedListType = listType.MakeGenericType(listElementType);
}
我也是说你应该看看GetGenericTypeDefinition()
方法,但是在我写完之前已经有AakashM的答案了
那你应该看看他的回答