Отражение: метод с общим аргументом и лямбда-выражением в качестве параметра

#c# #entity-framework #generics #reflection #lambda

#c# #entity-framework #общие #отражение #лямбда

Вопрос:

Я действительно не могу понять это…

Я пытаюсь достичь следующего результата, используя отражение:

 _builder.Entity<Post>().HasKey(p => p.Id);
  

Позвольте мне представить переменные… _builder имеет тип DbModelBuilder и Post имеет свойство Id типа Guid .

В приведенном ниже коде contentType оборачивается System.Type :

 var config = _builder.GetType()
    .GetMethod("Entity")
    .MakeGenericMethod(contentType.Type)
    .Invoke(_builder, null);

var hasKey = config.GetType().GetMethod("HasKey");

var expressionKey = typeof(Expression<>)
    .MakeGenericType(typeof(Func<,>)
    .MakeGenericType(contentType.Type, typeof(Guid)));

var paramEx = Expression.Parameter(contentType.Type, "t");
var lambdaEx = Expression.Lambda(Expression.Property(paramEx, "Id"), paramEx);

hasKey.MakeGenericMethod(typeof(Guid))
    .Invoke(_builder, new[] { lambdaEx });
  

HasKey определение может помочь:

 public EntityTypeConfiguration<TEntityType> HasKey<TKey>(Expression<Func<TEntityType, TKey>> keyExpression);
  

… где TEntityType должно быть типа Post и TKey типа Guid

Генерируется исключение типа TargetException (при последнем вызове для вызова выше) :

Объект не соответствует целевому типу.

Я перепробовал все идеи, которые мог придумать, и все равно не могу подобрать целевой тип.

Любая помощь приветствуется.

Комментарии:

1. Чтобы не быть блондином здесь, но не должен ли параметр экземпляра вашего последнего вызова быть config, а не _builder ? 🙂

2. Просто любопытно, так как я нахожу идею интригующей. Вы пытаетесь создать какой-то динамический EF ModelBuilder?

3. ха-ха-ха, тарелочка все еще спит, что позволяет мне набрать несколько очков 😉

4. Да, этот код в основном позволяет добавлять типы во время выполнения и сохранять их в базе данных SQL, модель проверяется на воссоздание базы данных и т.д… Динамический EF ModelBuilder да!

5. Очень интересно, я искал что-то подобное для доверенной среды плагинов и где они могут хранить свои данные…. Планируете ли вы сделать это проектом с открытым исходным кодом?

Ответ №1:

В вашем последнем вызове Invoke вы указали неправильный параметр экземпляра. Должно быть ‘config’, а не ‘_builder’

Ответ №2:

Глупый я, у меня нет оправданий…

How-to Entity Framework amp; отражение:

 var config = _builder.GetType()
    .GetMethod("Entity")
    .MakeGenericMethod(contentType.Type)
    .Invoke(_builder, null);

var hasKey = config.GetType().GetMethod("HasKey");

var expressionKey = typeof(Expression<>)
    .MakeGenericType(typeof(Func<,>)
    .MakeGenericType(contentType.Type, typeof(Guid)));

var paramEx = Expression.Parameter(contentType.Type, "t");
var lambdaEx = Expression.Lambda(Expression.Property(paramEx, "Id"), paramEx);

hasKey.MakeGenericMethod(typeof(Guid))
    .Invoke(config, new[] { lambdaEx });