疑惑
前段时间一直再用Entity Framework 6,写了一些公用的方法,在这个过程中发现了DbContext实现的接口IObjectContextAdapter,可以通过这个接口访问到更底层的ObjectContext对象,比如
((IObjectContextAdapter)ctx).ObjectContext
当时就觉得很奇怪,为什么不能直接获取,而需要一次转换,主要是奇怪C#是通过什么形式把ObjectContext给hide住的,不过当时也没多想,忙于完成工作。最近比较系统的再过C#知识点的时候,发现了Explicit Interface implementation, 回想起了这个之前的那个疑惑,又去看了一下才发现,原来就是基于这个原理,其实是一个C#特别常见的功能,当你在实现某些接口的时候,IDE就已经告诉你了是隐示实现接口(implicit implementation)还是显示实现接口(explicit implementation)。
关于 Explicit interface implementation
简单的一句话就是,如果你想用接口当中的成员,必须使用接口本身的一种实现方式,使用这种方式可以为一些特定的情况而隐藏特定的实现,比如说要实现两个接口InterfaceA,InterfaceB,这两个接口中有相同的成员方法,实现类里边就可以共存了。
public interface InterfaceA { void Test(); } public interface InterfaceB { void Test(); } public class RunTest : InterfaceA, InterfaceB { void InterfaceB.Test() { throw new NotImplementedException(); } void InterfaceA.Test() { throw new NotImplementedException(); } }
以这种方式实现后,实现类的实例是不能直接方法成员方法的。
DbContext 实现 IObjectContextAdapter
通过ILSpy反编译EntityFramwork.dll,并且查找DbContext后,就能看到实现IObjectContextAdapter的情况
/// <summary> /// Returns the Entity Framework ObjectContext that is underlying this context. /// </summary> /// <exception cref="T:System.InvalidOperationException">Thrown if the context has been disposed.</exception> [SuppressMessage("Microsoft.Design", "CA1033:InterfaceMethodsShouldBeCallableByChildTypes")] ObjectContext IObjectContextAdapter.ObjectContext { get { this.InternalContext.ForceOSpaceLoadingForKnownEntityTypes(); return this.InternalContext.ObjectContext; } }
是以explicit implementation的方式实现的接口,并且不直接暴露给外部,所以这也就是为什么Entity Framework 6更希望你用DbContext这种封装了N层的类,而不希望你在通常的情况下用更底层的类,但如果要用只能通过IObjectContextAdapter本身来调用这个成员。