是否可以在不使用Expression的情况下将类属性用作比较参数?

时间:2018-12-27 15:43:46

标签: c# reflection

我在类(Extensions)中使用了一种方法,该方法可以通过classInstance.GetIndex(c=>c.DT)这样的表达式获取用户输入:

    public static int GetIndex<T, Tres>(this T Class, Expression<Func<T, Tres>> propertySelector)
    {
        var body = (MemberExpression)propertySelector.Body;
        var propertyInfo = (PropertyInfo)body.Member;

        List<KeyValuePair<PropertyInfo, int>> indexList = GlobalClassList;

        int i = indexList.FindIndex(p => p.Key == propertyInfo);
        return i;
    }

该代码允许在先前填充的List<KeyValuePair<PropertyInfo, int>>列表上搜索用户输入。这样可以节省时间,每次都使用reflection查找课程。

我试图简化一些参数,而只需使用类实例元素classInstance.GetIndex(classInstance.DT),而不必使用(MemberExpression)propertySelector.Body

这可能吗?

我的代码示例:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;
using System.Runtime.CompilerServices;

namespace ptuga.Example
{
    class ptuga
    {

        static void Main()
        {

            // example for using data from an external file (e.g. read from a tab delimited file)
            List<string> simpleDataList = new List<string>
            {
                string.Format("A{0}B{0}C{0}D", "\t"),
                string.Format("E{0}F{0}G{0}H", "\t"),
                // ...
            };

            // data stored in List of MyClass structure
            // used to convert a simple list of strings  into a list of MyClass
            // using reflection and with no need to specify each class property
            List<MyClass> myClassList = MyClass.ReturnListOfMyClass(simpleDataList);

            Console.Write(string.Format("\n{0}\n",myClassList[0].string1));
            Console.Write(string.Format("{0}\n", myClassList[0].string2));
            Console.Write(string.Format("{0}\n", myClassList[0].string3));
            Console.Write(string.Format("{0}\n", myClassList[0].string4));

            // instance of class to use for getting the index
            MyClass myClass = new MyClass();

            // sets List<KeyValuePair<PropertyInfo, int>> list
            myClass.SetListWithClassDetails();
            // this type of list is much faster to retrieve the value than using reflection to get the order of the class at runtime
            // for every time it's required (e.g. loops)


            // accesses the List<KeyValuePair<PropertyInfo, int>> and returns the position of the property specified
            Console.Write(string.Format("\n{0}\n", myClass.GetIndex(c=>c.string1)));
            Console.Write(string.Format("{0}\n", myClass.GetIndex(c => c.string2)));
            Console.Write(string.Format("{0}\n", myClass.GetIndex(c => c.string3)));
            Console.Write(string.Format("{0}\n", myClass.GetIndex(c => c.string4)));
            // the index can be used to get the property order in the class without having to specify an integer
            // if the class has many properties and if the order changes it becauses difficult to track changes
            // e.g. I use it in a datagridview where columns are aligned with the class properties and where cells columns 
            // can be addressed using the integer that match with the class order

            Console.ReadKey();

        }
    }

    [AttributeUsage(AttributeTargets.Property, Inherited = false, AllowMultiple = false)]
    public sealed class OrderAttribute : Attribute
    {
        private readonly int order_;
        public OrderAttribute([CallerLineNumber]int order = 0)
        {
            order_ = order;
        }

        public int Order { get { return order_; } }
    }

    public class MyClass
    {
        [Order] public string string1 { get; set; }
        [Order] public string string2 { get; set; }
        [Order] public string string3 { get; set; }
        [Order] public string string4 { get; set; }

        public override string ToString()
        {
            return string.Format("{1}{0}{2}{0}{3}{0}{4}", "\t", string1, string2, string3, string4);
        }


        public static List<MyClass> ReturnListOfMyClass(List<string> dataList)
        {
            List<MyClass> myStructuredDataList = new List<MyClass>();

            // get class properties in order
            MyClass myClass = new MyClass();
            var properties = myClass.GetClassOrder();

            foreach (var line in dataList)
            {
                int index = 0;
                var lineSplit = line.Split('\t');
                MyClass myClassElement = new MyClass();

                foreach (PropertyInfo property in properties)
                {
                    property.SetValue(myClassElement, lineSplit[index]);
                    index++;
                }

                myStructuredDataList.Add(myClassElement);

            }

            return myStructuredDataList;

        }


    }




    public static class Extensions
    {

        private static List<KeyValuePair<PropertyInfo, int>> _globalClassList;

        public static List<KeyValuePair<PropertyInfo, int>> GlobalClassList
        {
            get 
            { 
                return _globalClassList; 
            }
            set 
            { 
                _globalClassList = value; 
            }

        }



        public static List<PropertyInfo> GetClassOrder<T>(this T Class)
        {
            var properties = from property in typeof(T).GetProperties()
                             where Attribute.IsDefined(property, typeof(OrderAttribute))
                             orderby ((OrderAttribute)property
                                       .GetCustomAttributes(typeof(OrderAttribute), false)
                                       .Single()).Order
                             select property;


            return properties.ToList();

        }



        public static List<KeyValuePair<PropertyInfo, int>> SetListWithClassDetails<T>(this T Class)
        {
            // get class properties in order
            MyClass myClass = new MyClass();
            var properties = myClass.GetClassOrder();


            List<KeyValuePair<PropertyInfo, int>> classPropertyInfo = new List<KeyValuePair<PropertyInfo, int>>();
            int index = 0;

            foreach (var item in properties)
            {
                classPropertyInfo.Add(new KeyValuePair<PropertyInfo, int>(item, index));
                index++;
            }

            //  sets global class variable
            GlobalClassList = classPropertyInfo;

            return classPropertyInfo;

        }

        public static int GetIndex<T, Tres>(this T Class, Expression<Func<T, Tres>> propertySelector)
        {
            var body = (MemberExpression)propertySelector.Body;
            var propertyInfo = (PropertyInfo)body.Member;

            List<KeyValuePair<PropertyInfo, int>> indexList = GlobalClassList;

            int i = indexList.FindIndex(p => p.Key == propertyInfo);
            return i;

        }


    }

}

0 个答案:

没有答案