2016-02-22 4 views
2

Скажем, у меня есть некоторый тип:Список свойств для анонимного типа

public class General 
{ 
    public int Id; 
    public string Name; 
    public DateTime modified 
} 

, я хочу некоторую функцию фильтра для Anonymous:

public void DoWorkOnSubset(List<General> generals, params Func<general, object> properties) 
{ 

} 

Как я мог бы взять список свойств и превратить его в анонимный тип

generals.Select(x => new { properties.ForEach(p => p.Invoke(x)) }); 
+0

Итак, в основном скопируйте тип? Что вы пытаетесь достичь с этим? – Rhumborl

+0

Анонимные типы расширяются до конкретной реализации во время компиляции. – Scorpion

+0

В основном я хочу подмножество типа анонимного, но я не знаю, пока свойства не будут переданы в –

ответ

2

Вы не можете создать новый анонимный тип во время выполнения, поскольку анонимные типы действительны t ypes, созданный компилятором за сценой. Код для создания этих типов недоступен для пользователей .NET через API, поэтому вам придется пройти через System.Reflection.Emit звонки, чтобы создавать свои собственные.

Следующая ближайшая вещь будет использовать динамический объект, такой как ExpandoObject, и установить его значения с помощью интерфейса IDictionary<string,object>. Вызовы будут иметь доступ к полям этого объекта, используя регулярный синтаксис.

EDIT: Если все, что вам нужно, это набор значений свойств таким образом, что вы можете получить доступ во время выполнения, вы можете использовать Dictionary<string,object>, как это:

generals.Select(x => 
    properties.ToDictionary(p => p.Name, p => p.Invoke(x)) 
); 
+1

Фактически вы можете создавать типы во время выполнения, посмотрите на [TypeBuilder] (https://msdn.microsoft.com/en-us/library/system.reflection.emit.typebuilder (v = vs.110) .aspx), хотя они будут мало полезны, поскольку ни один код не может использовать свойства напрямую.Однако вы можете реализовать интерфейсы нового типа, что упростит работу, но это, вероятно, будет работать против общего метода, который требует OP. –

+0

@ LasseV.Karlsen А, конечно, вы можете создавать свои собственные классы, если вы пройдете через emit. Однако это будет упражнение по кодированию строительного блока простого компилятора. – dasblinkenlight

1

В случае, если кто задавался вопросом Я понял способ добиться этого с анонимным типом. Вместо этого у меня есть IEnumerable свойств.

generals.Select(x => properties.Select(p => p.Invoke(x))); 

Я могу работать на это как IEnumerable вместо анонимного типа

+1

Еще лучше, вы могли бы запустить 'ToDictionary' и работать с ним в качестве словаря (см. Изменение для моего ответа на код). Проблема с 'IEnumerable ' заключается в том, что она может стать очень медленной из-за отложенного выполнения, если вы не конвертируете ее в список. – dasblinkenlight

+0

Спасибо за подсказку. Я, вероятно, переключусь на словарь, потому что тогда будет легче узнать, с чем я работаю, на основе ключа –

0

У меня было такое же решение и решить, что с помощью простого класса и наследования все мои объекты из него:

public class Entity 
{ 
    public Entity() 
    { 
     EntityPropertyDic = new Dictionary<string, object>(); 
    } 
    public object this[string propertyName] 
    { 
     get 
     { 
      if (EntityPropertyDic.ContainsKey(propertyName)) 
      { 
       return EntityPropertyDic[propertyName]; 
      } 
      else 
       throw new ArgumentException("PropertyName Is not exist!"); 
     } 
     set 
     { 
      OnColumnChanging(propertyName, ref value); 
      EntityPropertyDic[propertyName] = value; 
     } 
    } 

    private void OnColumnChanging(string propertyName, ref object value) 
    { 
     throw new NotImplementedException(); 
    } 

    protected Dictionary<string, object> EntityPropertyDic { get; set; } 
} 

так что вы можете сделать так:

public List<Entity> DoWorkOnSubset(List<General> generals, params string properties) 
{ 
    List<Entity> entityList = new List<Entity>(); 
    foreach(var general in generals) 
    { 
     var entity = new Entity(); 
     foreach(var prop in properties) 
     { 
      entity[prop] = general[prop]; 
     } 
     entityList.Add(entity); 
    } 

    return entityList; 
} 
Смежные вопросы