【问题标题】:C# Create getter delegate for specific item in ICollection or IEnumerableC# 为 ICollection 或 IEnumerable 中的特定项目创建 getter 委托
【发布时间】:2019-07-21 08:09:50
【问题描述】:

我正在尝试创建一个动态的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,因此在大多数情况下可能会以相同的方式进行处理。

是否可以编译一个可以直接获取特定 IEnumerable 元素而无需调用 ElementAt() 的 DynamicMethod,这可能会枚举整个集合,直到找到合适的元素? 我会欢迎使用更好的方法来解决这个问题,如果这太迂回了。

【问题讨论】:

    标签: c# delegates simulation ienumerable


    【解决方案1】:

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

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

    【讨论】:

    • 绝对是这样,但我试图支持不实现IList 的数据结构,而无需修改它们或为它们编写适配器。因此,如果可能的话,我更喜欢使用 getter 委托。
    • @Haus 如果你想支持不提供你需要的操作的数据结构,你要么需要修改它们,不使用它们,要么编写一个适配器来为它们添加所需的行为。当对象没有提供你想要的行为并且你自己没有添加它时,没有选择只拥有你想要的行为。
    猜你喜欢
    • 1970-01-01
    • 2015-11-25
    • 1970-01-01
    • 2012-01-18
    • 1970-01-01
    • 2013-01-26
    • 2011-08-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多