[英]Creating instance of a generic type from a instance of the type parameter
I have a BL consisting of a generic Repository and some specific implementations for a couple of entity types (My DAL is a Entity Framework 5 model). 我有一个由通用存储库和一些针对几种实体类型的特定实现组成的BL(我的DAL是Entity Framework 5模型)。 The Repository uses for almost all it's functionality the method Set() of the System.Data.Entity.DbContext.
存储库几乎使用System.Data.Entity.DbContext的Set()方法来实现所有功能。 I have some Expressions for things like getting siblings of a entity T, these won't work on the result of Set(Type entityType).
我有一些用于获取实体T的同级对象的表达式,这些表达式不适用于Set(Type entityType)的结果。
At one moment I have a instance of a non-generic DbEntityEntry. 有一瞬间,我有一个非通用DbEntityEntry的实例。 The entity is of type Object.
该实体的类型为Object。 When I use GetType() I get the approptiate Entity Type.
当我使用GetType()时,我得到适当的实体类型。 I know want to get the related entity using my functions in Repository.
我知道要使用存储库中的函数来获取相关实体。 Is there a way to do this from the non-generic DbEntityEntry.
有没有一种方法可以从非泛型DbEntityEntry中做到这一点。
I tried: 我试过了:
public Repository(T entity)
{
\\ Construction here
}
But I get a Repository<Object>
and the call to Set<Object>
returns nothing as expected. 但是我得到一个
Repository<Object>
,对Set<Object>
的调用未返回任何预期的结果。
I've searched for a way to do this but came up empty. 我一直在寻找一种方法来做,但是空了。
The constructor of a generic type is part of the specific class generated for its generic type argument. 泛型类型的构造函数是为其泛型类型参数生成的特定类的一部分。 For instance, the constructor of a
List<int>
is a different constructor than that of a List<string>
. 例如,
List<int>
的构造函数与List<string>
构造函数是不同的 。 In other words, the code that "finds" the type cannot exist inside the generic class. 换句话说,“查找”类型的代码不能存在于泛型类中。
As far as I know these are your two options: 据我所知,这是您的两个选择:
To create an instance using reflection, you can use: 要使用反射创建实例,可以使用:
Type genericType = typeof(List<>);
Type genericArgument = typeof(int);
Type specificType = genericType.MakeGenericType(genericArgument);
object instance = Activator.CreateInstance(specificType); // this is a List<int>
Take a look at this example posted by George Mauer in this thread. 让我们看一下George Mauer在此主题中发布的示例。 It requires .Net 4.0 or higher.
它要求.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;
}
You can use a slightly modified variant of this to create a matching Repository
instance: 您可以使用对此稍加修改的变体来创建匹配的
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);
}
If you can constraint your generic types to have a parameterless constructor, this problem can be solved pretty elegantly 如果可以将泛型类型约束为具有无参数构造函数,则可以很好地解决此问题
public Repository(T entity) where T : new()
{
T foo = new T(); //that's it
}
You can do: 你可以做:
T entity = default(T);
This works for both value types of T, as well as structs and classes. 这适用于T的值类型以及结构和类。 Where T is a class however it does require a parameterless constructor.
但是,在T是一个类的情况下,它确实需要无参数的构造函数。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.