Передайте список свойств объекта, которые будут использоваться для формирования нового объекта внутри запроса LINQ.

Звучит немного сложно, но вот что я пытаюсь сделать:

Я фильтрую определенные свойства MyObject в List<MyObject> в новый объект LINQ как:

 var filteredMyObjects = from r in myObjects select new { r.ComponentName, r.Group, r.Key };

Теперь проблема заключается в том, что свойства ComponentName, Group и Key должны поступать в качестве входных данных (например, List<string> имен свойств). Это используется в моей логике для экспорта данных в Excel.

Я пытался совместить это с этой идеей:

typeof(MyObject).GetProperty(property).GetValue(objectInstance) as string

Но не могу понять, как это реализовать.

ИЗМЕНИТЬ:

Смотрите пример того, что мне нужно для достижения:

List<string> userDefinedPropeties = new List<string> {Property1, Property2, Property3 ... }

var filteredMyObjects = from r in myObjects select new { r.Property1, r.Property2, r.Property3 ... };

Идеальный ответ будет выглядеть так, за исключением того, что это решение не работает в моем случае: свойство доступа Linq по переменной


person eYe    schedule 10.07.2015    source источник
comment
Я не совсем понимаю, что ты хочешь сделать. Вы хотите получить доступ к свойствам выбранных вами анонимных объектов? В таком случае, почему бы вам не создать новый класс, своего рода DTO, я думаю, который просто позволяет вам выбрать новый MyDtoObject { ... }?   -  person sara    schedule 10.07.2015
comment
Простой. Я хочу передать, какие свойства использовать внутри моего filteredMyObjects var.   -  person eYe    schedule 10.07.2015
comment
Почему бы вам не предоставить ListBox, чтобы пользователь мог выбирать из доступных свойств? Рефлексия всегда подвержена ошибкам.   -  person Tim Schmelter    schedule 10.07.2015
comment
Пропустить сопоставление MyObject с анонимным классом. В данном контексте не имеет смысла. Для файла Excel вы можете просто написать необходимые свойства MyObject.   -  person Kevin    schedule 10.07.2015
comment
Хорошая идея, Тим, но, к сожалению, у меня есть ограничения в дизайне пользовательского интерфейса.   -  person eYe    schedule 10.07.2015
comment
@eYe: какое ограничение, что вы должны использовать графический интерфейс, который может привести к неожиданным результатам или ошибкам и является громоздким? ;-)   -  person Tim Schmelter    schedule 10.07.2015
comment
Что этот функционал нельзя так вывести на передний план. Трудно объяснить, но я просто раб, выполняющий приказы здесь :)   -  person eYe    schedule 10.07.2015
comment
@eYe, вам нужно попытаться лучше объяснить свою проблему, я думаю, вы хотите заполнять данные из списка, а не из объекта напрямую, но я не уверен, что вы этого хотите   -  person konkked    schedule 10.07.2015
comment
Я хочу заполнить данные FILTERED из списка объектов. Однако параметры фильтрации, представленные комбинациями свойств, определяются пользователем.   -  person eYe    schedule 10.07.2015
comment
Я обновил вопрос с примером, извините, если вопрос немного сбивает с толку.   -  person eYe    schedule 10.07.2015


Ответы (2)


Вы не можете использовать для этого анонимный объект, лучше всего использовать объект Expando

//List<string> userDefinedPropeties is a parameter
List<dynamic> filteredMyObjects = new List<dynamic>();
foreach (var i in filteredMyObjects)
{

    dynamic adding = new ExpandoObject();
    foreach (var prop in userDefinedPropeties) 
    {
        adding[prop] = i.GetType().GetProperty(prop).GetValue(i);
    }

    filteredMyObjects.Add(adding);

}

// all of the elements of the filtered list can be accessed by using 
// item.`PropertyName`

Также лучшим способом сформулировать ваш вопрос было бы сказать, что вы хотите передать объект, который содержит только те свойства, которые запросил пользователь, не уверен, почему пользовательский интерфейс не сможет обрабатывать больше свойств, чем запрошено, но вы объяснили у вас нет контроля над дизайном

person konkked    schedule 10.07.2015
comment
Вероятно, он пытался избежать явного зацикливания, которое сильно замедляет работу при экспорте. - person sonne; 10.07.2015
comment
@sonne OP использует оператор linq для итерации, такой же дорогой, как цикл, только что оцененный лениво - person konkked; 10.07.2015
comment
@konkked Я пробовал этот подход, и время экспорта составило 52 секунды для ~ 4000 записей. Когда я использовал метод запроса, предоставленный в документах ClosedXML, время сократилось до ~ 500 мс. Так что, к сожалению, это не сработает. - person eYe; 10.07.2015
comment
@eYe, как вы получаете это перечисление? Если выражение Linq переводится в прямое действие (т.е. подготовленный sql stmt ), вы не получите такой же производительности, если вам нужно выполнить отражение - person konkked; 10.07.2015

Вы можете подделать динамические свойства, используя Dictionary:

public class CustomObject
{
    Dictionary<string, object> _properties = new Dictionary<string, object>();

    public CustomObject(dynamic parentObject, List<string> properties)
    {
        foreach (string propertyName in properties)
            _properties[propertyName] = parentObject.GetType().GetProperty(propertyName).GetValue(parentObject, null);
    }

    public object this[string name]
    {
        get
        {
            if (_properties.ContainsKey(name))
            {
                return _properties[name];
            }
            return null;
        }
        set
        {
            _properties[name] = value;
        }
    }
}

Пример использования:

var myObjects = new List<MyObject>()
{
    new MyObject(1, "Component1", 1, 1),
    new MyObject(2, "Component2", 2, 2),
    new MyObject(3, "Component3", 3, 3),
    new MyObject(4, "Component4", 4, 4),
    new MyObject(5, "Component5", 5, 5),
    new MyObject(6, "Component6", 6, 6),
    new MyObject(7, "Component7", 7, 7),
    new MyObject(8, "Component8", 8, 8),
};

var properties = new List<string>()
{
    "ComponentName", "Group", "Key"
};

List<CustomObject> myCustomObjects = new List<CustomObject>();
foreach (MyObject myObject in myObjects)
    myCustomObjects.Add(new CustomObject(myObject, properties));
person msmolcic    schedule 10.07.2015