创建通用基础实例 class
Creating instances of generic base class
我正在使用 Dapper.FluentMap
库,并尝试设置我的映射 classes 的自动注册。为此,我需要为每个 class 映射调用 FluentMapConfiguration.AddMap<T>(EntityBase<T>)
。
我可以这样做:
public class TypeAMap : EntityMap<TypeA> {}
public class TypeBMap : EntityMap<TypeB> {}
public class TypeCMap : EntityMap<TypeC> {}
public void Register(FluentMapConfiguration configuration)
{
configuration.AddMap(new TypeAMap());
configuration.AddMap(new TypeBMap());
configuration.AddMap(new TypeCMap());
// I have a hundred of these, you can see where I'm going...
}
当您忘记注册地图并想知道为什么您的数据无法正确加载时,这显然是一个问题。所以关于自动注册的一些反思:
public void Register(FluentMapConfiguration configuration)
{
var maps = GetType().Assembly.GetExportedTypes().Where(t =>
!t.IsAbstract &&
!t.IsInterface &&
t.BaseType is { IsGenericType: true } &&
t.BaseType.GetGenericTypeDefinition() == typeof(EntityMap<>)
).ToArray();
foreach (var map in maps)
{
var baseType = typeof(EntityMap<>);
var typeArguments = map.BaseType.GetGenericArguments();
var genericType = baseType.MakeGenericType(typeArguments);
var instance = Activator.CreateInstance(genericType);
configuration.AddMap((dynamic) instance);
}
}
但是当它到达对 Activator.CreateInstance
的调用时,它失败了,出现 MissingMethodException
、Cannot create abstract class
。看起来它正在尝试创建 EntityBase<TypeA>
而不是 TypeAMap
的实例,并且由于 EntityBase<T>
是抽象的 class,我收到了错误。那么我该如何正确构建我的实例呢?
Where
调用过滤掉程序集中的类型,仅包括非抽象类型、非接口类型以及 EntityMap<anything>
的直接子class 类型。所以 maps
包含类型 TypeAMap
、TypeBMap
、TypeCMap
等
然后对于其中的每一个,您的代码获取其基础 class 并尝试实例化 that。查看for循环中的注释代码:
// suppose "map" is typeof(TypeAMap)
var baseType = typeof(EntityMap<>);
// typeArguments would be an array containing typeof(TypeA) only.
var typeArguments = map.BaseType.GetGenericArguments();
// genericType would be typeof(EntityMap<TypeA>)
var genericType = baseType.MakeGenericType(typeArguments);
// now you try to instantiate a EntityMap<TypeA>, and fails, because EntityMap<TypeA> is abstract
var instance = Activator.CreateInstance(genericType);
因为你想做 new TypeAMap()
、new TypeBMap()
等的反射版本,而且我们知道 maps
包含你想实例化的那些类型,你可以这样做:
foreach (var map in maps)
{
var instance = Activator.CreateInstance(map);
configuration.AddMap((dynamic) instance);
}
您根本不需要关心 EntityMap
的泛型类型参数。当动态绑定器尝试推断 AddMap
.
的类型参数时,它将弄清楚这一点
我正在使用 Dapper.FluentMap
库,并尝试设置我的映射 classes 的自动注册。为此,我需要为每个 class 映射调用 FluentMapConfiguration.AddMap<T>(EntityBase<T>)
。
我可以这样做:
public class TypeAMap : EntityMap<TypeA> {}
public class TypeBMap : EntityMap<TypeB> {}
public class TypeCMap : EntityMap<TypeC> {}
public void Register(FluentMapConfiguration configuration)
{
configuration.AddMap(new TypeAMap());
configuration.AddMap(new TypeBMap());
configuration.AddMap(new TypeCMap());
// I have a hundred of these, you can see where I'm going...
}
当您忘记注册地图并想知道为什么您的数据无法正确加载时,这显然是一个问题。所以关于自动注册的一些反思:
public void Register(FluentMapConfiguration configuration)
{
var maps = GetType().Assembly.GetExportedTypes().Where(t =>
!t.IsAbstract &&
!t.IsInterface &&
t.BaseType is { IsGenericType: true } &&
t.BaseType.GetGenericTypeDefinition() == typeof(EntityMap<>)
).ToArray();
foreach (var map in maps)
{
var baseType = typeof(EntityMap<>);
var typeArguments = map.BaseType.GetGenericArguments();
var genericType = baseType.MakeGenericType(typeArguments);
var instance = Activator.CreateInstance(genericType);
configuration.AddMap((dynamic) instance);
}
}
但是当它到达对 Activator.CreateInstance
的调用时,它失败了,出现 MissingMethodException
、Cannot create abstract class
。看起来它正在尝试创建 EntityBase<TypeA>
而不是 TypeAMap
的实例,并且由于 EntityBase<T>
是抽象的 class,我收到了错误。那么我该如何正确构建我的实例呢?
Where
调用过滤掉程序集中的类型,仅包括非抽象类型、非接口类型以及 EntityMap<anything>
的直接子class 类型。所以 maps
包含类型 TypeAMap
、TypeBMap
、TypeCMap
等
然后对于其中的每一个,您的代码获取其基础 class 并尝试实例化 that。查看for循环中的注释代码:
// suppose "map" is typeof(TypeAMap)
var baseType = typeof(EntityMap<>);
// typeArguments would be an array containing typeof(TypeA) only.
var typeArguments = map.BaseType.GetGenericArguments();
// genericType would be typeof(EntityMap<TypeA>)
var genericType = baseType.MakeGenericType(typeArguments);
// now you try to instantiate a EntityMap<TypeA>, and fails, because EntityMap<TypeA> is abstract
var instance = Activator.CreateInstance(genericType);
因为你想做 new TypeAMap()
、new TypeBMap()
等的反射版本,而且我们知道 maps
包含你想实例化的那些类型,你可以这样做:
foreach (var map in maps)
{
var instance = Activator.CreateInstance(map);
configuration.AddMap((dynamic) instance);
}
您根本不需要关心 EntityMap
的泛型类型参数。当动态绑定器尝试推断 AddMap
.