Как указано в заголовке - я хочу определить выражение, которое описывает только тело метода. Пример:
// 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 - больше хлопот, чем удобно.
Это контекст. Я старался быть коротким, но есть много препятствий.