Activator.CreateInstance创建EF Core实体时ILazyLoader未注入问题
EF Core反射创建实体时ILazyLoader未注入导致延迟加载失效解决方案
问题根因
当前调用的Activator.CreateInstance(type)为无参重载,运行时默认匹配类型的无参数构造函数执行。你的ORMLawEntity中标记[JsonConstructor]的无参构造刚好符合匹配规则,接收ILazyLoader参数的构造函数未被调用,因此_lazyLoader字段始终为null,导航属性访问时无法执行延迟加载逻辑。
可行方案
方案1:显式调用带参构造(稳定性最高)
利用EntityBase中已持有的IServiceProvider解析ILazyLoader实例,显式查找匹配的带参构造函数创建实例,避免构造匹配歧义。
替换原有反射创建实例的代码如下:
Type propertyType = GetPropertyType("ORMLawEntity"); Type type = propertyType.GetGenericArguments().Single(); object obj; // 从当前请求Scope的服务容器解析ILazyLoader,避免生命周期问题 var lazyLoader = serviceProvider.GetRequiredService<ILazyLoader>(); // 显式查找签名匹配的构造函数 var constructor = type.GetConstructor(new[] { typeof(ILazyLoader) }); if (constructor != null) { // 传入依赖调用带参构造 obj = constructor.Invoke(new object[] { lazyLoader }); } else { // 兜底逻辑:实体未实现带ILazyLoader的构造时,走无参构造 obj = Activator.CreateInstance(type); }
方案2:使用Activator带参重载(代码最简洁)
Activator.CreateInstance本身支持传入构造参数数组,运行时会自动匹配参数签名一致的构造函数,代码量更少:
Type propertyType = GetPropertyType("ORMLawEntity"); Type type = propertyType.GetGenericArguments().Single(); var lazyLoader = serviceProvider.GetRequiredService<ILazyLoader>(); // 传入构造参数,自动匹配对应构造 object obj = Activator.CreateInstance(type, lazyLoader);
注意:如果实体后续新增其他参数数量、类型相近的构造函数,该方法可能出现匹配歧义,生产环境优先选择方案1显式指定构造。
方案3:优化实体鲁棒性(兼容多场景创建)
如果不想调整反射创建逻辑,也可以修改实体代码,增加空值保护,同时支持无参构造场景下的依赖解析:
修改ORMLawEntity代码如下:
public class ORMLawEntity : EntityBase { private readonly ILazyLoader _lazyLoader; [JsonConstructor] public ORMLawEntity() { base.PrimaryKey = "idLaw"; base.EntityName = "Law"; // 若项目中持有全局服务提供者引用,可在此处解析ILazyLoader // 注意:需确保解析的ILazyLoader与当前DbContext生命周期一致,避免已释放异常 } public ORMLawEntity(ILazyLoader lazyLoader) { base.PrimaryKey = "idLaw"; base.EntityName = "Law"; _lazyLoader = lazyLoader; } [Key] public long idLaw { set; get; } private ORMCatalogValueEntity _LawTypeCIDEntity; public virtual ORMCatalogValueEntity LawTypeCIDEntity { set { _LawTypeCIDEntity = value; } get { // 增加空判断,避免_lazyLoader为null时抛出空引用 if (_lazyLoader == null) return _LawTypeCIDEntity; return _lazyLoader.Load(this, ref _LawTypeCIDEntity); } } }
注意事项
- 当前
EntityBase中的serviceProvider字段为private访问级别,如果后续将实体创建逻辑抽到独立类/扩展方法中,需要将其访问级别调整为protected或提供受控的访问入口。 ILazyLoader与EF Core的DbContext同属Scope生命周期,不要从根服务提供者解析该实例,否则会出现对象已释放的异常。- 如果项目中存在多个实体构造的反射逻辑,可以将上述创建逻辑封装为泛型扩展方法,复用代码避免重复编写。
内容的提问来源于stack exchange,提问作者javad bayat
相关产品推荐
相关产品推荐

