简体   繁体   English

如何通过 C# 中的代码中定义的变量名称查找对数组的引用?

[英]How to find a reference to an array by the name of the variable as defined in the code in C#?

Obviously, I'm not looking for the classic:显然,我不是在寻找经典:

string[] garden = {"Tulip"};
Console.WriteLine(garden[0]);

but rather, doing the same with a string:而是对字符串做同样的事情:

string[] garden = {"Tulip"};
string gardenname = "garden";
string[] cool_NEW_array = ArrayByName(gardenname);
Console.WriteLine(cool_NEW_array[0])

I'm curious as to whether there is some actually existing version of "ArrayByName" which would let me find an array by using a string which is its name.我很好奇是否存在一些实际存在的“ArrayByName”版本,它可以让我通过使用作为其名称的字符串来查找数组。 Thanks in advance!提前致谢!

It is impossible, as I know, and this may cause lots of problems about reflexion and generated IL.据我所知,这是不可能的,这可能会导致很多关于反射和生成 IL 的问题。

There is the nameof operator and meanings to get variables names in the caller of a method, but it is not intended for your goal.在方法的调用者中有nameof运算符和含义来获取变量名称,但它不适合您的目标。

Perhaps there some reflection tools to do that, but I don't know.也许有一些反射工具可以做到这一点,但我不知道。

Perhaps you can do that using huge reflexion on a whole assembly by parsing all classes, all instances, all fields and properties members, all methods and all local vars of these methods...也许您可以通过解析所有类、所有实例、所有字段和属性成员、所有方法以及这些方法的所有局部变量来对整个程序集使用巨大的反射来做到这一点......

In all case, you may encounter problems with duplicates vocabulary.在任何情况下,您都可能会遇到重复词汇的问题。

But you can use a Dictionary keyed by the name of the intended variable name.但是您可以使用以预期变量名称为键的Dictionary

Thus you create a sort of data table.因此,您创建了一种数据表。

We use a class variable as private to store some one-dimension string arrays and public methods to add and remove these arrays from the collection as well as a method to find which can match having one string using Contains (or equality if you want).我们使用 class 变量作为私有变量来存储一些一维字符串 arrays 和公共方法来添加和删除这些 arrays 以及从集合中找到一个字符串包含的匹配方法(如果需要的话)。

The collection该系列

static private readonly Dictionary<string, string[]> RegisteredArrays 
  = new Dictionary<string, string[]>();

The register and unbregister methods register 和 unbregister 方法

static public void RegisterArray(string name, string[] array)
{
  if ( !RegisteredArrays.ContainsKey(name)
    && !RegisteredArrays.ContainsValue(array) )
    RegisteredArrays.Add(name, array);
}

static public void UnregisterArray(string name)
{
  if ( RegisteredArrays.ContainsKey(name) )
    RegisteredArrays.Remove(name);
}

static public void UnregisterArray(string[] array)
{
  if ( RegisteredArrays.ContainsValue(array) )
  {
    var item = RegisteredArrays.FirstOrDefault(kvp => kvp.Value == array).Key;
    RegisteredArrays.Remove(item);
  }
}

The find method查找方法

static public IEnumerable<string[]> FindRegisteredArray(string name)
{
  foreach ( var item in RegisteredArrays )
    if ( item.Key == name )
      yield return item.Value;
}

Test测试

static void Test()
{
  string[] garden1 = { "Tulip", "Rose" };
  string[] garden2 = { "Flower 1", "Flower 2", "Flower 3" };

  RegisterArray(nameof(garden1), garden1);
  RegisterArray(nameof(garden2), garden2);

  string gardenname = "garden1";

  foreach ( var array in FindRegisteredArray(gardenname) )
    Console.WriteLine(string.Join(",", array));

  foreach ( var array in FindRegisteredArray("garden2") )
    Console.WriteLine(string.Join(",", array));
}

Output Output

Tulip,Rose
Flower 1,Flower 2,Flower 3

Improvements改进

You can create a whole class to offer the desired behavior您可以创建一个完整的 class 来提供所需的行为

static public class NamedStringArrayManager
{
  static private readonly Dictionary<string, string[]> RegisteredArrays
    = new Dictionary<string, string[]>();

  static public void Register(string name, string[] array)
  {
    if ( !RegisteredArrays.ContainsKey(name)
      && !RegisteredArrays.ContainsValue(array) )
      RegisteredArrays.Add(name, array);
  }

  static public void Unregister(string name)
  {
    if ( RegisteredArrays.ContainsKey(name) )
      RegisteredArrays.Remove(name);
  }

  static public void Unregister(string[] array)
  {
    if ( RegisteredArrays.ContainsValue(array) )
    {
      var item = RegisteredArrays.FirstOrDefault(kvp => kvp.Value == array).Key;
      RegisteredArrays.Remove(item);
    }
  }

  static public IEnumerable<string[]> Find(string name)
  {
    foreach ( var item in RegisteredArrays )
      if ( item.Key == name )
        yield return item.Value;
  }
}
static void Test()
{
  string[] garden1 = { "Tulip", "Rose" };
  string[] garden2 = { "Flower 1", "Flower 2", "Flower 3" };

  NamedStringArrayManager.Register(nameof(garden1), garden1);
  NamedStringArrayManager.Register(nameof(garden2), garden2);

  string gardenname = "garden1";

  foreach ( var array in NamedStringArrayManager.Find(gardenname) )
    Console.WriteLine(string.Join(",", array));

  foreach ( var array in NamedStringArrayManager.Find("garden2") )
    Console.WriteLine(string.Join(",", array));
}

We can also create a generic manager for any type我们还可以为任何类型创建通用管理器

static public class NamedInstanceManager<T>
{
  static private readonly Dictionary<string, T> RegisteredArrays
    = new Dictionary<string, T>();

  static public void Register(string name, T instance)
  {
    if ( !RegisteredArrays.ContainsKey(name)
      && !RegisteredArrays.ContainsValue(instance) )
      RegisteredArrays.Add(name, instance);
  }

  static public void Unregister(string name)
  {
    if ( RegisteredArrays.ContainsKey(name) )
      RegisteredArrays.Remove(name);
  }

  static public void Unregister(T instance)
  {
    if ( RegisteredArrays.ContainsValue(instance) )
    {
      var item = RegisteredArrays.FirstOrDefault(kvp => kvp.Value.Equals(instance)).Key;
      RegisteredArrays.Remove(item);
    }
  }

  static public IEnumerable<T> Find(string name)
  {
    foreach ( var item in RegisteredArrays )
      if ( item.Key == name )
        yield return item.Value;
  }
}

Or simply any object:或者只是任何 object:

static public class NamedInstanceManager
{
  static private readonly Dictionary<string, object> RegisteredArrays
    = new Dictionary<string, object>();

  static public void Register(string name, object instance)
  {
    if ( !RegisteredArrays.ContainsKey(name)
      && !RegisteredArrays.ContainsValue(instance) )
      RegisteredArrays.Add(name, instance);
  }

  static public void Unregister(string name)
  {
    if ( RegisteredArrays.ContainsKey(name) )
      RegisteredArrays.Remove(name);
  }

  static public void Unregister(object instance)
  {
    if ( RegisteredArrays.ContainsValue(instance) )
    {
      var item = RegisteredArrays.FirstOrDefault(kvp => kvp.Value.Equals(instance)).Key;
      RegisteredArrays.Remove(item);
    }
  }

  static public IEnumerable<object> Find(string name)
  {
    foreach ( var item in RegisteredArrays )
      if ( item.Key == name )
        yield return item.Value;
  }
}

Also we can manage registering and unregistering several differents names for the same reference and so on... by throwing an exception, returning a bool or do nothing.我们还可以管理注册和取消注册相同引用的多个不同名称等...通过抛出异常、返回布尔值或什么都不做。

Here the code only accept to add a name or a reference only if both is not already in the collection.此处代码仅接受添加名称或引用,前提是两者都不在集合中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM