我正在使用Value Injecters使用LoopValueInjection从1种类型映射到另一种类型,并使用一些自定义逻辑覆盖SetValue(对象v)方法。我试图检测何时传入HashSet并通过HashSet并将方法应用于其中的每个项目以进行一些清理。我遇到的问题是因为参数只是一个对象,我不知道HashSet中的项目类型。例如,它可以是HashSet或HashSet。
以下是我目前的代码,但是我收到了InvalidCastException。
protected override object SetValue(object v)
{
if (type.Name == "HashSet`1")
{
var genericType = type.GetGenericArguments()[0];
// this line throws the InvalidCastException
var cleanHashSet = (HashSet<object>)Activator.CreateInstance(type);
foreach (var item in (HashSet<object>)v) // I'm sure this cast will throw as well
{
cleanHashSet.Add(Clean(item));
}
return cleanHashSet;
}
return base.SetValue(v);
}
我想主要的问题是,一旦我确定它实际上是某种HashSet,我怎么能循环通过作为对象传入的HashSet?我也在想我需要创建一个特定类型的新空HashSet,这样我就可以将每个被清理的项目放入其中。
答案 0 :(得分:7)
在.NET中,只有接口和委托类型可以是共同变体和反变体。因此无法将HashSet<SomeType>
投射到HashSet<object>
。
您希望将v
转换为IEnumerable
接口的非通用版本
dynamic cleanHashSet = Activator.CreateInstance(type);
foreach (object item in (IEnumerable)v)
{
cleanHashSet.Add(Clean(item));
}
如果您不想使用dynamic
关键字,则需要使用反射调用Add
方法
object cleanHashSet = Activator.CreateInstance(type);
var method = type.GetMethod("Add");
foreach (object item in (IEnumerable)v)
{
method.Invoke(cleanHashSet, new object[] { Clean(item) });
}
答案 1 :(得分:0)
使用:
bool isHashSet = typeof(HashSet<object>).IsAssignableFrom(type);
或
object x = ...
HashSet<object> hs = x as HashSet<object>;
if (hs != null)
{
// use hs
}
如果您确实指定了<T>
,请使用它而不是object
。
HashSet<T>
implements ICollection<T>
,IEnumerabel<T>
,IEnumerable
。如果您知道T
可以枚举和添加,那意味着什么。否则枚举只枚举。