C # Создать делегат получателя для определенного элемента в ICollection или IEnumerable - PullRequest
0 голосов
/ 27 февраля 2019

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

Я хотел бы сделать это на основе отражения, чтобы любой будущий разработчик мог взять существующий класс и включить его в Environment без необходимости реализации дополнительных функций.Если возможно, я бы хотел добавить поддержку интерфейсов ICollection и / или IEnumerable, чтобы можно было использовать существующие классы, которые их реализуют.Например, возможность зарегистрировать Dictionary будет означать, что среда будет перечислять все пары ключ-значение в качестве переменных среды, где ключ превращается в уникальную строку, а значение - это то, что будет предоставлено при запросе.

Пример того, как это может быть реализовано:

public class Environment
{
  private delegate object GetterDelegate();

  private Dictionary<string, GetterDelegate> environmentVariables_;

  public IEnumerable<string> EnvironmentVariables
  {
    get => environmentVariables_.Keys;
  }

  public object this[string name]
  {
    get => environmentVariables_[name]();
  }

  public Environment()
  {
    environmentVariables_ = new Dictionary<string, GetterDelegate>();
  } 

  public void Register( string name, ICollection collection )
  {
    int i = 0;
    foreach( var element in collection )
      environmentVariables_.Add( $"name_{i++}", GetterDelegate );
  }

  public void Register( string name, IEnumerable enumerable )
  {
    int i = 0;
    foreach( var element in enumerable )
      environmentVariables_.Add( $"name_{i++}", GetterDelegate );
  }

  public void Register<T,V>( string name, Dictionary<T,V> dictionary )
  {
    // TODO: Custom logic instead of Key.ToString()
    foreach( var pair in dictionary )
      environmentVariables_.Add( $"name_{pair.Key.ToString()}", GetterDelegate );
  }

  public void Register( string name, FieldInfo field )
  {
    environmentVariables_.Add( name, GetterDelegate );
  }

}

Для этого я хотел бы иметь возможность динамически компилировать методы получения, которые могут напрямую обращаться к конкретному элементу вместо того, чтобы иметькаждый раз вызывать IEnumerable.ElementAt(), поскольку это может быть невероятно медленным в зависимости от реализации класса.И поскольку ICollection реализует IEnumerable, в большинстве случаев он может обрабатываться аналогичным образом.

Можно ли скомпилировать DynamicMethod, который может напрямую получать определенный элемент IEnumerable без необходимости вызывать ElementAt (), который, вероятно, будет перечислять всю коллекцию, пока не будет найден нужный элемент? Я бы приветствовал и лучший способ решить эту проблему, если это слишком много.

1 Ответ

0 голосов
/ 27 февраля 2019

Не используйте IEnumerable или ICollection, если вам нужен доступ к элементам по индексу.Ни один из этих интерфейсов не поддерживает это.

IList - это интерфейс, представляющий данные, к которым можно получить доступ по индексу.

...