我正在尝试通过反射创建DbEntityEntry<T>
以进行测试。它的构造函数是内部的,但我想调用它并传入一个实体:
public DbEntityEntry<T> Entry<T>(T entity) where T : class
{
Type constructedType = typeof(DbEntityEntry<T>);
BindingFlags flags = BindingFlags.NonPublic | BindingFlags.Instance;
object x = Activator.CreateInstance(constructedType, flags, null, new object[] { entity }, null);
我明白了:
未找到类型'System.Data.Entity.Infrastructure.DbEntityEntry`1 [[System.Object,mscorlib,Version = 4.0.0.0,Culture = neutral,PublicKeyToken = b77a5c561934e089]]的构造函数。
构造函数的来源是:
internal DbEntityEntry(InternalEntityEntry internalEntityEntry)
{
DebugCheck.NotNull(internalEntityEntry);
_internalEntityEntry = internalEntityEntry;
}
任何创建实例的方法?
更新:
原始代码实际上是从Marc Gravell以前的答案之一中解除的,但由于这篇文章是关闭的候选人,我将在建议中使用Gravell的答案提供另一次尝试:
Type[] argTypes = new Type[] { typeof(T) };
object[] argValues = new object[] { entity };
BindingFlags flags = BindingFlags.NonPublic | BindingFlags.Instance;
ConstructorInfo ctor = typeof (DbEntityEntry<T>).GetConstructor(flags, null, CallingConventions.Any, argTypes, null);
object obj = ctor.Invoke(argValues);
ctor
为null,因此无法找到构造函数。
答案 0 :(得分:1)
尝试使用它。
public DbEntityEntry<T> Entry<T>(T entity)
where T : class
{
ConstructorInfo constructor = null;
try
{
// Binding flags exclude public constructors.
constructor = typeof(DbEntityEntry<T>)
.GetConstructor(BindingFlags.Instance | BindingFlags.NonPublic, null,
new Type[] { typeof(InternalEntityEntry) }, null);
}
catch (Exception exception)
{
throw new Exception("Error Finding Constructor", exception);
}
if (constructor == null) // || constructor.IsAssembly)
// Also exclude internal constructors ... note, were including for this example
throw new Exception(string.Format("A private or " +
"protected constructor is missing for '{0}'.", typeof(DbEntityEntry<T>).Name));
return (DbEntityEntry<T>)constructor.Invoke(new object[] { entity });
}
答案 1 :(得分:1)
而不是询问如何使用反射实例化第三方类型,而不是询问如何更改代码以使其可测试且不需要黑客攻击。如果你查看你发布的DbEntityEntry
ctor,你会看到它需要一个InternalEntityEntry
对象 - 你需要实例化的另一个内部类(带反射)。所以你最终会自己创建很多内部对象,即使你不熟悉它们应该如何真正协同工作,如果EF碰巧以不同的方式创建这些对象,你的测试可能会没用,因为它们仍然可以通过该计划将无法运作。此外,因为它是内部的东西,它可以在下一个版本中更改,并且您的测试可能无法正常使用新版本。您的帖子中没有足够的详细信息可以提供更好的建议。请注意,您可以使用DbContext.Entry()方法使用公共API创建DbEntityEntry
。