【问题标题】:Type casting, a runtime alternative to Cast<T>?类型转换,Cast<T> 的运行时替代方案?
【发布时间】:2012-10-12 08:13:04
【问题描述】:

我有一个 IList&lt;object&gt;,其中每个对象都是 T 类型的实例(我在编译时不知道)。

我需要一个IList&lt;T&gt;。我不能使用 Cast,因为我在编译时不知道类型,并且没有可以使用的 Cast(Type) 重载。

这是我目前所拥有的:

private object Map(IList<ApiCallContext> bulk)
{
    // god-awful way to build a IEnumerable<modelType> list out of Enumerable<object> where object is modelType.
    // quoting lead: "think whatever you do it will be ugly"
    Type modelType = model.Method.ModelType;

    if (bulk.Count > 0)
    {
        modelType = bulk.First().Parameters.GetType();
    }
    Type listType = typeof(List<>).MakeGenericType(modelType);
    object list = Activator.CreateInstance(listType);
    foreach (object value in bulk.Select(r => r.Parameters))
    {
        ((IList)list).Add(value);
    }
    return list;
}

我在想的是,也许我可以创建一个新的 LooseList 类来实现 IList 并且只处理强制转换,看起来比我目前拥有的更好,但听起来还是太笨拙了。

【问题讨论】:

  • 请问这样做的目的是什么?如果您在编译时不知道 T,您将无法以强类型的方式使用您的 IList,对吧?
  • 重点是我需要用这个列表提供一个库,它使用泛型来解析列表并写入一个 CSV 文件。
  • 你需要喂食的方法是什么样的?任何T 都需要List&lt;T&gt;,还是固定为某个特定值?
  • void WriteRecords&lt;T&gt;(IEnumerable&lt;T&gt; rows)。那是无关紧要的。他们尝试使用T 构建表达式以获取我类型中的属性;然后爆炸了。

标签: c# linq reflection


【解决方案1】:

如果您确实需要完全按照您所说的那样做,我首先将其分为“特定于上下文的代码”和“可重用代码”。实际上你想要这样的东西:

public static IList ToStrongList(this IEnumerable source, Type targetType)

我会实现,通过编写一个强类型方法,然后通过反射调用它:

private static readonly MethodInfo ToStrongListMethod = typeof(...)
    .GetMethod("ToStrongListImpl", BindingFlags.Static | BindingFlags.NonPublic);

public static IList ToStrongList(this IEnumerable source, Type targetType)
{
    var method = ToStrongListMethod.MakeGenericMethod(targetType);
    return (IList) method.Invoke(null, new object[] { source });
}

private static List<T> ToStrongListImpl<T>(this IEnumerable source)
{
    return source.Cast<T>().ToList();
}

【讨论】:

  • 你仍然需要反射来调用WriteRecords&lt;T&gt;(IEnumerable&lt;T&gt;) 方法,因为没有静态已知类型你不能直接调用它。
  • @Porges:Reflection 或 dynamic,当然会在幕后使用反射,但从编码的角度来看更简单 :)
  • 但是当你打电话给ToStrongList 时,targetType 是不知道的,除非你在打电话之前做一些检查,那为什么不在ToStringList 内部做呢?
  • @Wasp:关键是你会在Map 内进行检查,就像它已经在做的那样......并且通过反射调用泛型方法,我们只需要使用反射一次,而不是一次调用Cast&lt;T&gt;和一次调用ToList&lt;T&gt;
  • 好吧,明白了,我认为 ToStrongList 是为了取代 Map,这就是为什么我要强调这一点并认为它必须进入 ToStringList :)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-08-22
  • 1970-01-01
  • 2010-10-07
  • 1970-01-01
相关资源
最近更新 更多