2014-10-17 91 views
0

我试图通过反射创建一个DbEntityEntry<T>用于测试目的。它的构造是内部的,但我想调用它,并通过在实体:实例化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; 
    } 

任何方式创建一个实例?

UPDATE:

原代码实际上是由马克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为空,所以再次找不到构造函数。

回答

0

而是询问如何实例化一个第三方类型与反思的问如何改变你的代码,以便它是可测试的,不需要黑客。如果你看看你发布的DbEntityEntry ctor,你会发现它需要一个InternalEntityEntry对象 - 你将不得不实例化的另一个内部类(带反射)。所以即使你没有深入了解它们应该如何真正一起工作,并且如果EF碰巧以不同的方式创建这些对象,你最终也会自己创建大量内部对象,因此测试可能无用,因为它们仍然可以通过该方案将无法正常工作。此外,因为它是内部的东西,它可以在下一个版本中更改,并且您的测试可能无法正确使用新版本。您的帖子中没有足够的详细信息能够提供更好的建议。请注意,您可以使用公共API和DbContext.Entry()方法创建DbEntityEntry

+0

我确实认为这是正确的途径。 – 2014-10-17 16:49:48

+0

如果您不满意答案,请解释原因。 – Pawel 2016-03-01 16:34:24

+0

我正在为DbEntityValidationException的扩展方法编写一个测试。为了测试它,我需要创建一个DbEntityValidationResult的实例,但这需要一个DbEntityEntry的实例,并且在那里我发现了这个问题。我同意你关于改变代码,但在我的情况下,我不明白我该怎么做。有任何想法吗? – 2017-01-24 21:58:26

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 }); 
} 
+0

看起来非常好,除了'InternalEntityEntry'是EF组件的'internal' ...任何想法如何解决这个问题? – 2014-10-17 16:21:31

+0

可能Type.GetType(“System.Data.Entity.Internal.InternalEntityEntry”),但你必须仔细检查 - 我不认为我有正确的EF加载tho ...我会看看如果我可以得到EF 5加载。 – 2014-10-17 16:25:57

+0

谢谢特拉维斯,但我们可以通过这种方式检索内部类型吗? – 2014-10-17 16:31:50