Создайте метод динамически, где возвращаемый тип известен во время компиляции

2

данный следующий класс:

public class Stock {
   public string Name;
   public double Price;
}

и у меня есть следующий DataFactory:

public class DataFactory {
   public Stock Stock = new Stock();   

   public DataFactory Name(string name) {
     Stock.name = name;
     return this;
   }

   public DataFactory Price(double price) {
      Stock.Price = price;
      return this;
   }
}

может следующий код:

.....
   new DataFactory().Name("ATVI").Price(50)
....

быть написано как:

....
   new DataFactory().ATVI().Price(50)
....

без внедрения ATVI() на заводе? Это будет работать, если я заранее создаю метод динамически. Но возможно ли это, не зная, какой метод будет вызван? Поэтому я ищу какой-то хук при жизни, который уведомляет меня о неизвестных свойствах/методах.

И если это работает, можно ли при вызове Price() вызывать intellisense?

Не знаю, как это можно назвать, извините, если существуют дублирующие темы.

С наилучшими пожеланиями, Йозеф

  • 0
    Вы просто ненавидите написание строковых литералов или просто ненавидите написание Name ?
  • 1
    Если вы извлекаете свои данные из DynamicObject, вы можете переопределить TryGetMethod. Но я сомневаюсь, что есть способ обеспечить интеллигентность,
Показать ещё 2 комментария
Теги:

2 ответа

2
Лучший ответ

Предполагая, что у вас есть конечный предопределенный набор текстовых литералов, который меняется не часто, вы можете просто сгенерировать перечисление (или даже класс строковых констант), например, используя шаблоны T4, и использовать его как: DataFactory.Name(Tickers.ATVI).Price(50)
Это будет подход, который лучше всего соответствует семантике проблемы и способностям языка С# и инструментов.

Кстати, тот метод цепочки, который вы планируете использовать, представляет собой комбинацию шаблона компоновщика и свободного интерфейса, см. Пример в С#

Если вы все еще хотите скрыть это как вызов метода, у вас есть несколько вариантов:

  1. Предварительно создайте список методов, используя шаблоны T4 в частичном классе или в качестве методов расширения для вашей фабрики данных. Вы можете выбрать список литералов из вашего хранилища данных внутри шаблона T4. Это довольно распространенный подход. Поскольку у вас будут предварительно сгенерированные методы, itellisence будет работать с этим подходом. узнать больше о T4
  2. Используйте DLR и dynamic. Это откладывает поиск метода до времени выполнения, и вы можете создать собственный динамический объект, который будет принимать любой вызов метода, а затем взять это имя метода и передать его в качестве аргумента методу Name. Intellisence не будет работать с этим подходом, так как у вас нет метаданных в сборке относительно ваших методов. Как создать динамический объект
  3. Используйте dynamic и дополнительно создайте расширение intellisence, подробнее см. Custom Intellisense Extension

Вы можете пойти еще дальше, написать анализатор Roslyn и установить его в Visual Studio для автоматического исправления кода из DataFactory().Name("ATVI") в DataFactory().ATVI(), то есть, если у вас есть время/ресурс. Посмотрите пример анализа кода

Как всегда, ответ "это зависит", а контекст - это все, поэтому трудно сказать, какое решение будет лучшим для вас. Я предпочел бы пойти на самый простой 1), особенно учитывая сложность и стоимость обслуживания 2) и 3)

Пожалуйста, дайте мне знать, если вам нужна более подробная информация о любом из вариантов Надеюсь, это поможет!

  • 0
    Очень полезно! Спасибо за все варианты. Я думаю, что попробую все из них и решу тогда, что я должен использовать. Я вернусь, если мне понадобится дополнительная помощь.
  • 0
    Рад, что смог помочь, @JosefBiehler!
0

следующий код

new DataFactory().Name("ATVI").Price(50)

не может быть написано как

new DataFactory().ATVI().Price(50)

на самом деле, ни один из этих кодов не работает. потому что вы не можете получить функцию "Price" из функции "Name" и "ATVI()" не является допустимой функцией

Мне не больно, что вы пытаетесь достичь, данный код вернет функцию. но если я не ошибаюсь, вы хотите установить "Цена" по "Имя". тогда я думаю, что вам нужен словарь классов

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

  • 0
    Как вы можете видеть в моем примере кода, Name() возвращает экземпляр типа DataFactory а не функцию? Так что да, этот код должен работать, хотя я не проверял его, а писал на лету, когда писал этот вопрос. Может быть, я не совсем понимаю вашу точку зрения :-)

Ещё вопросы

Сообщество Overcoder
Наверх
Меню