代码之家  ›  专栏  ›  技术社区  ›  Dean Meehan

可以从c中的公共字符串类创建列表#

  •  -1
  • Dean Meehan  · 技术社区  · 12 年前

    我正在使用C#创建一个应用程序,并希望能够通过我的120个字符串轻松地进行foreach()循环。所有这些字符串的构造如下:

    public class _currentweekapi
        {
            public string _1_artist { get; set; }
            public string _2_artist { get; set; }
            public string _3_artist { get; set; }
            ...
        }
    

    是否可以通过foreach()循环来遍历所有值。字符串是从JSON提要中自动设置的,因此我无法将值直接放入列表中。

    我已经读过这个话题,并理解通过“反思”有很多方法,但我是C#的新手,读它对我来说没有任何意义。

    有人能帮我找到一个解决方案吗?具体说明我该如何实施?

    4 回复  |  直到 12 年前
        1
  •  2
  •   Shaun Wilde    12 年前

    使用反射非常容易——先试试这个

    var properties = typeof(_currentweekapi).GetProperties();
    
    foreach(PropertyInfo info in properties) {
      if (info.Name.EndsWith("artist") {
        // do something amazing
      }
    }
    

    参见- http://msdn.microsoft.com/en-us/library/kyaxdd3x.aspx 了解更多信息

        2
  •  1
  •   dylansweb    12 年前

    您应该尝试做的第一件事是,不要像类定义所做的那样,将字符串存储在显式命名的属性中。最合适的场景似乎是List<字符串>键入可以在类中容纳所有这些的属性。这也意味着你已经准备好了你的清单。
    因此,如果您能够更改类或使用另一个类,它接受JSON提要,并对List<字符串>,而不是明确地设置120个属性。

    像这样:

    public class ArtistData
    {
        public List<string> Artists{ get; set; }
    
        public ArtistData()
        {
            this.Artists = new List<string>(0);
        }
    
        public void PopulateArtists(string jsonFeed)
        {
            // here something desrializes your JSON, allowing you to extract the artists...
            // here you would be populating the Artists property by adding them to the list in a loop...
        }
    }
    

    然后,您在属性Artists中有您的列表,可以直接使用该列表,也可以通过执行以下操作返回该列表:

    string[] artists = myInstance.Artists.ToArray();
    

    然而,你似乎已经表示,你无法改变这样一个事实,即它们最终作为你向我们展示的类中的单独属性提供给你,所以。。。

    假设你别无选择,只能从你展示的类开始,这里有一种方法可以通过所有这些值进行循环,正如你所要求的那样,所需要的就是将你的类实例传递到下面的一个方法中,作为每个方法所需的一个参数:

        // this will return a list of the values contained in the properties...
        public List<string> GetListFromProperties<T>(T instance)
        {
            Type t = typeof(T);
            PropertyInfo[] props = t.GetProperties(BindingFlags.Public | BindingFlags.Instance);
    
            // As a simple list...
            List<string> artists = new List<string>(props.Length);
            for (int i = 0; i < props.Length; i++)
            {
                if(!props[i].Name.Contains("_artist")){ continue; }
                artists.Add(props[i].GetValue(instance, null).ToString());
            }
    
            return artists;
        }
    
        // this will return a dictionary which has each artist stored
        // under a key which is the name of the property the artist was in.
        public Dictionary<string,string> GetDictionaryFromProperties<T>(T instance)
        {
            Type t = typeof(T);
            PropertyInfo[] props = t.GetProperties(BindingFlags.Public | BindingFlags.Instance);
    
            // As a dictionary...
            Dictionary<string,string> artists = new Dictionary<string,string>(props.Length);
            for (int i = 0; i < props.Length; i++)
            {
                if(artists.ContainsKey(props[i].Name) || !props[i].Name.Contains("_artist")){ continue; }
                artists.Add(props[i].Name, props[i].GetValue(instance, null).ToString());
            }
    
            return artists;
        }
    

    任何一种都应该有帮助,但不要使用字典,因为这会带来更多的开销,除非你真的需要知道每个艺术家的财产名称,在这种情况下,它比简单的列表更有帮助。

    顺便说一句,由于这些方法是泛型的,也就是说,它们接受T类型的参数,因此相同的方法将适用于ANY类实例,而不仅仅是您现在正在处理的实例。

    请记住:尽管目前这对你来说可能非常方便,但这不一定是最好的方法。比这更好的是,我最初提出的建议是重新开始上课,这样就不需要这种事情了。

        3
  •  0
  •   Andras Csehi    12 年前

    你可以这样做:

            List<string> list = new List<string>();
            foreach (var property in _currentweekapi.GetType().GetProperties())
            {
                list.Add(property.GetValue(_currentweekapi, null));               
            }
    
        4
  •  0
  •   Enigmativity    12 年前

    如果您可以确保没有其他类型的属性,那么这将起作用:

    var list =
        typeof(_currentweekapi)
            .GetProperties()
            .Select(pi => (string)pi.GetValue(x, null))
            .ToList();