2014-10-17 2 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 null, поэтому конструктор снова не найден.

ответ

0

Вместо того чтобы спрашивать, как экземпляр 3-й типа партии с отражением спросить, как изменить код так, чтобы он проверяемый и не требует хаков. Если вы посмотрите на ctor, который вы опубликовали, вы увидите, что объект InternalEntityEntry - еще один внутренний класс, который вам нужно создать (с отражением). Таким образом, вы в конечном итоге создаете множество внутренних объектов самостоятельно, даже если у вас нет глубоких знаний о том, как они должны работать вместе, и если EF будет создавать эти объекты по-другому, ваши тесты могут оказаться бесполезными, поскольку они все равно могут пройти, хотя программа не будет работать. Более того, потому что это внутреннее содержимое, оно может измениться в следующей версии, и ваш тест может не работать корректно с новой версией. В вашем сообщении недостаточно подробностей, чтобы лучше советовать. Обратите внимание, что вы можете создать DbEntityEntry с использованием общедоступного API с помощью метода DbContext.Entry().

+0

Я верю, что это правильный путь для подхода. –

+0

Если вы отрицаете ответ, объясните, почему. – Pawel

+0

Я пишу тест для метода расширения, который у меня есть для DbEntityValidationException. Чтобы проверить его, мне нужно создать экземпляр DbEntityValidationResult, но для этого нужен экземпляр DbEntityEntry, и там я нашел этот вопрос SO. Я согласен с вами в изменении кода, но в моем сценарии я не вижу, как это сделать. Есть идеи? –

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 ... Любая идея, как обойти это? –

+0

Возможно Type.GetType ("System.Data.Entity.Internal.InternalEntityEntry"), но вам придется дважды проверить - я не думаю, что у меня есть правильный EF загруженный ... Я посмотрю, могу ли я получить EF 5. –

+0

Спасибо Travis, но можем ли мы получить внутренний тип таким образом? –