我在类(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;
}
}
}