我使用值注入器从一个类型映射到另一个使用LoopValueInjection和覆盖SetValue(对象v)方法与一些自定义逻辑。我试图检测何时传入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,以便我可以将每个项目清理到其中。
在。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) });
}
使用说明:
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>
实现ICollection<T>
, IEnumerabel<T>
, IEnumerable
。如果您知道T
,那么您可以枚举和添加,否则只能枚举。