3

我正在使用 Value Injecters 使用 LoopValueInjection 将一种类型映射到另一种类型,并使用一些自定义逻辑覆盖 SetValue(object 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,以便我可以将每个被清理的项目放入其中。

4

2 回答 2

8

在 .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) });
}
于 2013-03-19T04:15:06.550 回答
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> 实现 ICollection<T>, IEnumerabel<T>, IEnumerable. 如果您知道T可以枚举和添加,这意味着什么。否则枚举只枚举。

于 2013-03-19T04:16:21.073 回答