从type参数的实例创建泛型类型的实例

时间:2013-05-02 11:52:41

标签: c# generics

我有一个由通用存储库组成的BL和一些实体类型的一些特定实现(My DAL是一个Entity Framework 5模型)。存储库几乎所有功能都使用System.Data.Entity.DbContext的Set()方法。我有一些表达式,比如获取实体T的兄弟,这些不会对Set(Type entityType)的结果起作用。

有一次我有一个非泛型DbEntityEntry的实例。该实体的类型为Object。当我使用GetType()时,我得到了适当的实体类型。我知道想要在Repository中使用我的函数来获取相关实体。有没有办法从非泛型DbEntityEntry中执行此操作。

我试过了:

public Repository(T entity)
{
    \\ Construction here
}

但是我收到了Repository<Object>,并且对Set<Object>的调用没有按预期返回任何内容。

我已经找到了一种方法来做到这一点,但是空了。

4 个答案:

答案 0 :(得分:2)

泛型类型的构造函数是为其泛型类型参数生成的特定类的一部分。例如,List<int>的构造函数是不同的构造函数,而不是List<string>的构造函数。换句话说,“找到”类型的代码不能存在于泛型类中。

据我所知,这是你的两个选择:

  • 将对象转换为实际类型(类似工厂的解决方案)
  • 使用反射来创建泛型类实例

要使用反射创建实例,您可以使用:

Type genericType = typeof(List<>);
Type genericArgument = typeof(int);
Type specificType = genericType.MakeGenericType(genericArgument);
object instance = Activator.CreateInstance(specificType); // this is a List<int>

答案 1 :(得分:2)

看看George Mauer在this帖子中发布的这个例子。它需要.Net 4.0或更高版本。

dynamic DynamicCast(object entity, Type to)
{
    var openCast = this.GetType().GetMethod("Cast", BindingFlags.Static | BindingFlags.NonPublic);
    var closeCast = openCast.MakeGenericMethod(to);
    return closeCast.Invoke(entity, new[] { entity });
}
static T Cast<T>(object entity) where T : object
{
    return entity as T;
}

您可以使用稍微修改过的变体来创建匹配的Repository实例:

public static dynamic CreateRepository(object entiry, Type targetType)
{
    Type BaseType = typeof(Repository<>);   
    Type ConcreteType = BaseType.MakeGenericType(targetType);
    var Instance = Activator.CreateInstance(ConcreteType, entiry);

    return DynamicCast(Instance, ConcreteType);
}

答案 2 :(得分:0)

如果你可以限制你的泛型类型有一个无参数构造函数,这个问题可以很优雅地解决

public Repository(T entity) where T : new()
{
    T foo = new T(); //that's it
}

答案 3 :(得分:0)

你可以这样做:

T entity = default(T);

这适用于T的值类型,以及结构和类。其中T是一个类,但它确实需要一个无参数的构造函数。