【问题标题】:Property name as variable属性名称作为变量
【发布时间】:2011-10-18 17:55:35
【问题描述】:

我需要找到数据库中每个字符串列的最大大小作为设计另一个数据库的信息之一。我对源数据库的唯一访问是通过 Web 服务。我可以为许多列中的每一个都做它以找到最大的大小,但我希望它是通用的,以便我以后可以使用它。

我写了这个非常简化的版本以使其易于理解。最后两行发明了语法,这是我需要帮助的地方。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ConsoleApplication1
{
    public class myClass
    {
        private string s;
        public string S
        {
            get { return s; }
            set { s = value; }
        }
        private int i;
        public int I
        {
            get { return i; }
            set { i = value; }
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            Type myClassType = typeof(myClass);
            System.Reflection.PropertyInfo[] propertyInfo = myClassType.GetProperties();
            Dictionary<string, int> property = new Dictionary<string, int>();

            foreach (System.Reflection.PropertyInfo info in propertyInfo)
               if (info.PropertyType == typeof(System.String))
                    property.Add(info.Name, -1);

            myClass[] myPa = new myClass[2];
            myPa[0] = new myClass();
            myPa[0].S = "1";
            myPa[0].I = 0;
            myPa[1] = new myClass();
            myPa[1].S = "12";
            myPa[1].I = 1;

这是我需要帮助的地方。我发明了c[pair.key]。如何引用我知道名称的属性?

            foreach (myClass c in myPa)
                foreach (KeyValuePair<string, int> pair in property)
                    if (c[pair.Key].Length > pair.Value)
                        property[pair.Key] = c[pair.Key].Length;

            foreach (KeyValuePair<string, int> pair in property)
                Console.WriteLine("Property: {0}, Biggest Size: {1}", pair.Key, pair.Value);
        }
    }
}

输出应该是:

Property: S Biggest Size: 2

【问题讨论】:

    标签: c# reflection


    【解决方案1】:

    以下内容就足够了:

    static void Main()
    {
        // Demo data
        myClass[] myPa = new myClass[2];
        myPa[0] = new myClass();
        myPa[0].S = "1";
        myPa[0].I = 0;
        myPa[1] = new myClass();
        myPa[1].S = "12";
        myPa[1].I = 1;
    
        PrintMaxLengthsOfStringProperties(myPa);
    }
    
    public static void PrintMaxLengthsOfStringProperties<T>(IEnumerable<T> items)
    {
        var t = typeof(T);
        t.GetProperties().Where(p => p.PropertyType == typeof(string)) // TODO: Add other filters
                            .SelectMany(p => items.Select(o => (string)p.GetValue(o, null)).Select(v => new { Property = p, Value = v }))
                            .GroupBy(u => u.Property)
                            .Select(gu => new { Property = gu.Key, MaxLength = gu.Max(u => u.Value != null ? u.Value.Length : 0) })
                            .ToList()
                            .ForEach(u2 => Console.WriteLine("Property: {0}, Biggest Size: {1}", u2.Property.Name, u2.MaxLength))
                            ;
    }
    

    虽然您可能会在“GetProperties”结果集上添加一些额外的过滤器(例如取出静态过滤器或索引属性等。

    它使用了几个 Linq 扩展函数,即“Where”、“GroupBy”、“SelectMany”、“Select”和“Max”以及使用匿名类型。

    【讨论】:

    • 这行得通,我接受了。但我会坚持在另一个问题中不依赖 Linq 的解决方案,尽管我怀疑没有。
    【解决方案2】:

    不太确定我是否理解正确,但是:

    如果只是在你的类中使用索引属性 this[propertyname] 会返回一个指定属性的值,比如一个对象。

        public class myClass
        {
            ....
            ....
            public object this[string propertyname]
            {
                get { /*use reflection to return property value, so Object*/ }
    
            }
            ....
            ....
        }
    

    这意味着,恐怕你不能只写c[pair.key].Length,因为Object 没有Length 属性。您需要将其转换为所需的类型(在您的情况下为 string),并且仅在使用 Length 属性之后。

    如果这不是您所要求的,请重新提出您的问题。

    【讨论】:

    • 那个类只是一个简化。我无法控制 Web 服务返回的每一行都是一个实例的真实类。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-01-07
    • 1970-01-01
    • 1970-01-01
    • 2011-11-30
    • 2013-05-16
    • 1970-01-01
    相关资源
    最近更新 更多