Как да получите единична колона с LINQ в анонимен метод

Как да получите единична колона с анонимен метод, използвайки linq израз. Ето моят код и той не работи:

public IEnumerable<object> GetPropertyValues<T>(string propName) where T : class
{
    return base.Query<T>().AsEnumerable()
        .Where(x => x.GetType().GetProperty(propName).Name == propName)
        .Select(x => x.GetType().GetProperty(propName).GetValue(x, null));
}

Ето кода в необобщен метод:

base.Query<Product>().Select(x => x.ProductName).AsEnumerable();

Благодаря предварително.


person derodevil    schedule 14.12.2013    source източник
comment
не работи не ни дава полезна информация. Какъв е смисълът на вашата клауза Where? GetProperty(propName) ще върне само свойство с това име... това е целият смисъл.   -  person Jon Skeet    schedule 15.12.2013
comment
Той вероятно се опитва да направи base.Query<Product>().Pluck("ProductName").AsEnumerable();   -  person cwharris    schedule 15.12.2013
comment
Имам предвид като Select ProductName [Name] From Product в SQL или base.Query<Product>().Select(x => new { Name = x.ProductName }).AsEnumerable();   -  person derodevil    schedule 15.12.2013


Отговори (3)


Това условие е неправилно, защото когато свойството propName липсва, то се срива, вместо да връща false:

.Where(x => x.GetType().GetProperty(propName).Name == propName)

Ако искате да кажете „динамичният тип има свойството propName“, правилното условие за него ще изглежда така:

.Where(x => x.GetType().GetProperty(propName) != null)

Имайте предвид, че това е необходимо само когато някои, но не всички, подкласове на T имат желаното свойство propName. Ако свойството присъства в самия T, можете да получите свойството предварително и да направите останалата част от заявката по този начин:

var theProp = typeof(T)..GetProperty(propName);
return base.Query<T>().AsEnumerable().Select(x => theProp.GetValue(x, null));
person Sergey Kalinichenko    schedule 14.12.2013

След като извикате AsEnumerable(), цялото по-нататъшно филтриране ще се случи в паметта, а не в SQL. По този начин можете да направите:

var prop = typeof(T).GetProperty(propName);
return base.Query<T>().AsEnumerable().Select(t => prop.GetValue(t));

но това ще избере всички колони на T в паметта, преди да филтрира само до една. За да направите филтрирането в SQL, ще трябва динамично да конструирате израз:

var prop = typeof(T).GetProperty(propName);
var parameter = Expression.Parameter(typeof(T));
var memberAccess = Expression.MakeMemberAccess(parameter, prop);
var selector = Expression.Lambda<Func<T, TProperty>>(memberAccess, parameter);
return base.Query<T>().Select(selector);
person ChaseMedallion    schedule 14.12.2013
comment
Искам да получа всички стойности въз основа на конкретно свойство. Опитах вашето предложение и получих грешка на TProperty. Можете ли да обясните повече? - person derodevil; 15.12.2013
comment
Променям TResult в обект и той работи. Имам още въпрос, мога ли да поставя анонимен тип по този начин? base.Query<Product>().Selec(x => new { Name = x.ProductName }); - person derodevil; 15.12.2013

За изброяване на всякакъв тип обекти...

public static IEnumerable<Object> Pluck<Object>(this IEnumerable<Object> source, string propName)
{
    return source
        .Select(x => new {
            obj: x
            prop: x.GetType().GetProperty(propName)
        })
        .Where(x => x.prop != null)
        .Select(x => x.prop.GetValue(x.obj));
};

За изброяване на един тип обект...

public static IEnumerable<Object> Pluck<T>(this IEnumerable<T> source, string, propName)
{
    var prop = typeof(T).GetProperty(propName);
    return prop == null
         ? Enumerable.Empty<Object>()
         : source.Select(x => prop.GetValue(x));
};
person cwharris    schedule 14.12.2013