使用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初始化的对象出现NullRefere

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。。。但这似乎是个非常糟糕的主意。