当它作为一个对象提供时,如何循环HashSet <t>并且T可以是任何东西?</t>

时间:2013-03-19 04:11:06

标签: c# reflection valueinjecter

我正在使用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,这样我就可以将每个被清理的项目放入其中。

2 个答案:

答案 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可以枚举和添加,那意味着什么。否则枚举只枚举。