从字符串值引用标量属性

时间:2016-04-10 09:27:10

标签: wpf entity-framework

我有combobox,其中包含entity的标量属性列表。我需要在combobox

中搜索用户指定的属性

当我将该属性作为字符串时,如何引用该属性?

类似于DBSet<>的实体。

示例:

if (order.Firstname != null && order.Firstname.ToLower().Contains(textBoxSearch.Text.ToLower()))

在上面的示例中,我需要在运行时将Firstname替换为Surname或任何其他属性,具体取决于用户选择的内容。

2 个答案:

答案 0 :(得分:1)

您可以随时使用reflection,对于您的情况,您需要这些内容:

    static void Main(string[] args)
    {
        var entity = new Entity {
            Height = 172,
            FirstName = "Foo",
            Birthday = new DateTime(1, 1, 1995)
        };

        var firstName = GetEntityProperty<string>(entity, "FirstName");
    }

    public static T GetEntityProperty<T>(object entity, string propertyName)
    {
        var type = entity.GetType();
        var property = type.GetProperty(propertyName);

        return (T)property.GetValue(entity);
    }

答案 1 :(得分:0)

提供的解决方案有效,但它不是强类型的,因此对属性重命名是明智的。可以使用强类型方法,但需要一些设置。但是,部分设置非常通用,可以重复使用:

public class Order
{
    public String OrderNo { get; set; }
    public String FirstName { get; set; }
    public String LastName { get; set; }
    public String Misc { get; set; }
}   

// clearly define properties that allow search
public enum OrderSearchableProp
{
    OrderNo = 1,
    FirstName = 2,
    LastName = 3
}

class Program
{
    // strongly-type requires an explicit mapping between property and its expression within the order object
    static Dictionary<OrderSearchableProp, Expression<Func<Order, String>>> OrderSearchableMap = new Dictionary<OrderSearchableProp, Expression<Func<Order, string>>>()
    {
        { OrderSearchableProp.OrderNo, o => o.OrderNo },
        { OrderSearchableProp.FirstName, o => o.FirstName },
        { OrderSearchableProp.LastName, o => o.LastName },
    };

    // this gets a PropertyInfo based from an Expression. It should be placed into a generic utility class 
    // credit goes to Daniel - http://stackoverflow.com/a/17116267/2780791
    public static PropertyInfo GetPropertyFromExpression<T, TProp>(Expression<Func<T, TProp>> GetPropertyLambda)
    {
        MemberExpression Exp = null;

        //this line is necessary, because sometimes the expression comes in as Convert(originalexpression)
        if (GetPropertyLambda.Body is UnaryExpression)
        {
            var UnExp = (UnaryExpression)GetPropertyLambda.Body;
            if (UnExp.Operand is MemberExpression)
            {
                Exp = (MemberExpression)UnExp.Operand;
            }
            else
                throw new ArgumentException();
        }
        else if (GetPropertyLambda.Body is MemberExpression)
        {
            Exp = (MemberExpression)GetPropertyLambda.Body;
        }
        else
        {
            throw new ArgumentException();
        }

        return (PropertyInfo)Exp.Member;
    }

    public static IList<Order> getFilteredOrders(int propFilterValue, IList<Order> orders, String needle)
    {
        var filterValue = (OrderSearchableProp)propFilterValue;
        var filterProp = OrderSearchableMap[filterValue];
        var lowNeedle = needle?.ToLower() ?? String.Empty;

        return orders.Where(o =>
            {
                var propInfo = GetPropertyFromExpression<Order, String>(filterProp);
                var propValue = (String) propInfo.GetValue(o) ?? String.Empty;
                return propValue.ToLower().Contains(lowNeedle);
            }).ToList();
    }

    static void Main(string[] args)
    {
        // can be used to populate the combo items
        // otherwise, not used in this example
        OrderSearchableProp[] enumValues = (OrderSearchableProp[])Enum.GetValues(typeof(OrderSearchableProp));

        // test orders
        var orderList = new List<Order>()
            {
                new Order() { OrderNo = "1234ABC", FirstName = "George", LastName = "Taylor", Misc = "Extra information"},
                new Order() { OrderNo = "AB10", FirstName = "Anonymous", LastName = "X", Misc = "No comment"}
            };

        // test OrderNo search
        var searchProp = (int) OrderSearchableProp.OrderNo;
        var foundOrders = getFilteredOrders(searchProp, orderList, "ABC");

        // test FirstName search
        searchProp = (int)OrderSearchableProp.FirstName;
        foundOrders = getFilteredOrders(searchProp, orderList, "a");

        // test LastName search with empty string
        searchProp = (int)OrderSearchableProp.LastName;
        foundOrders = getFilteredOrders(searchProp, orderList, "");

        // empty return
        searchProp = (int)OrderSearchableProp.OrderNo;
        foundOrders = getFilteredOrders(searchProp, orderList, null);

    }
}