C#为ICollection或IEnumerable中的特定项创建getter委托

问题描述 投票:0回答:1

我正在尝试创建一个动态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 );
  }

}

为了实现这一点,我希望能够动态编译可以直接访问特定元素的getter方法,而不必每次都调用IEnumerable.ElementAt(),因为根据类的实现,这可能会非常慢。由于ICollection实施IEnumerable,在大多数情况下可能会以相同的方式处理。

是否有可能编译一个DynamicMethod,它可以直接获取一个特定的IEnumerable元素,而不必调用ElementAt(),它可能会枚举整个集合,直到找到正确的元素为止?如果这个问题过于迂回,我会欢迎更好的方法来解决这个问题。

c# delegates simulation ienumerable
1个回答
1
投票

如果您需要能够通过索引访问项目,请不要使用IEnumerableICollection。这些接口都不支持。

IList是表示可以通过索引访问的数据的接口。

© www.soinside.com 2019 - 2024. All rights reserved.