Создать дерево выражений, которое определяет только лямбда-тело - PullRequest
0 голосов
/ 16 ноября 2018

Как указано в заголовке - я хочу определить выражение, которое описывает только тело метода. Пример:

// Definition
public Expression<T> SomeExpression<T>() { ... }

// Usage
entities.Select(e => e.SomeExpression<int>())

// Instead of 
entities.Select(SomeExpression<int>())

Я знаю, что могу определить выражение делегата как

Expression<Func<int>> SomeExpression() { ... }

Но так как это описывает полноправного делегата, я должен использовать его как .Select(SomeExpression()). Это проблема, потому что единственный способ, которым я могу беспрепятственно использовать это, это присоединить SomeExpression к самому экземпляру сущности.

Я знаю, что в этом нет особого смысла - короче говоря, я пытаюсь найти обходной путь для глупой ошибки, допущенной давно в проекте. Правильное исправление не может быть и речи.

Примечания:

  • SomeExpression должен быть определен в экземпляре объекта e
  • SomeExpression должен работать на e (я думаю о Expression.Consntant(this))
  • SomeExpression должен поддерживаться EntityFramework
  • SomeExpression должен возвращать общее значение, например, string или int

Дополнительная информация

Я пытаюсь решить проблему плохого наследования - у меня есть сущность ( Training ), у которой есть внешний ключ к другой сущности ( Course ). Учебный объект состоит из базового класса (с тем же именем - Training ) и нескольких производных ( Instances ). Проблема в том, что внешний ключ , который абсолютно идентичен для всех, содержится в свойстве производных классов, а не в базовом. Поскольку у меня общий уровень услуг, каждый раз, когда я получаю сущность Training , мне нужно выполнить несколько условных приведений ко всем производным классам, чтобы добраться до сущности Course .

SomeExpression само по себе эффективно переводится в нечто вроде

t => t is InternalInstance
    ? (t as InternalInstance).Course,
    : t is OpenInstance
         ? // So on an so forth...

Более подробно вы можете прочитать в этой теме .

Почему лямбда не работает в моем случае? Я упустил обобщения в этом вопросе, чтобы сделать его простым, однако в моем случае SomeExpression, и его класс должен зависеть от нескольких универсальных параметров, так как в моем решении есть несколько веб-проектов, каждый из которых имеет свой собственный курс и Экземпляры типы.

Именно поэтому идеальным местом для этого выражения будет тип Training - у него уже есть необходимые общие параметры. Если я не помещу это туда, я должен создать сервис и использовать контейнер для их разрешения. Тогда мне придется внедрять этот сервис везде, где я хочу использовать это сопоставление - в основном это общие сервисы и просмотр моделей . Добавление его к общим службам не является проблемой, но навязчиво, так как вам нужна дополнительная зависимость, просто для выполнения сопоставления. Модели просмотра проблематичны, поскольку они используют конфигурацию AutoMapper , чтобы инкапсулировать отображение и хранить его внутри. AutoMapper создает и кэширует карты задолго до запуска контейнера, что разрешается в NullReference . Есть способы обеспечить время выполнения сервиса, но это увеличивает шаблон как в модели представления, так и в контроллере. На этом этапе использование выражения, чтобы получить Course - больше хлопот, чем удобно.

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

...