使用FormatterServices.GetUninitializedObject初始化的对象出现NullRefere
本文关键字:NullRefere 对象 FormatterServices GetUninitializedObject 初始化 使用 | 更新日期: 2023-09-27 18:26:50
我正在模拟DbContext,在我的测试中,我希望确保实体被标记为删除。当我在模拟上下文中标记每个对象时,我用静态字典跟踪每个实体:
public DbEntityEntry<T> Entry<T>(T entity) where T : class
{
var entry = (DbEntityEntry<T>)FormatterServices.GetUninitializedObject(typeof(DbEntityEntry<T>));
var state = entityStates[entity];
entry.State = state;
return entry;
}
public void SetEntityState(object entity, System.Data.EntityState state)
{
entityStates.Add(entity, state);
Entry(entity).State = state;
}
private static Dictionary<object, EntityState> entityStates = new Dictionary<object, EntityState>();
我无法用Activator.CreateInstance()
实例化DbEntityEntry
,所以我用FormatterServices.GetUninitializedObject()
进行了实例化。
问题是这一行:
entry.State = state;
尝试分配到此属性会导致:
NullReferenceException: Object reference not set to an instance of an object.
很明显,在给定函数名称的情况下,对象并没有初始化,但我不确定为什么不能在不引发此异常的情况下分配给对象的属性。
FWIW,测试看起来像:
TripManager.DeleteTripsByForeignKey(int carId);
var trip1 = _fakeDbContext.Trips.FirstOrDefault(t => t.TripId == 1);
var entry = _fakeDbContext.Entry(trip1);
Assert.AreEqual(EntityState.Deleted, entry.State);
FormatterServices.GetUninitializedObject
不对类型调用任何构造函数。这意味着具有默认值或在构造函数中设置的字段不会被设置。如果查看State
属性的定义(https://github.com/mono/entityframework/blob/master/src/EntityFramework/Infrastructure/DbEntityEntry.cs-请原谅mono版本的链接),您可以看到setter依赖于_internalEntityEntry
,它在构造函数中设置:
internal DbEntityEntry(InternalEntityEntry internalEntityEntry)
{
_internalEntityEntry = internalEntityEntry;
}
当然,这就是为什么你不应该摆弄FormatterServices.GetUninitializedObject
:)
如果你真的知道自己在做什么,你可以显式地调用内部构造函数,并模拟InternalEntityEntry
。。。但这似乎是个非常糟糕的主意。