使用Reflection </t>实例化DbEntityEntry <t>

时间:2014-10-17 15:59:26

标签: c# entity-framework

我正在尝试通过反射创建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,因此无法找到构造函数。

2 个答案:

答案 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