Чому деякі властивості об’єктів мають UnaryExpression, а інші MemberExpression?


76

Діючи на відповідь на мій Вибір властивості моделі, використовуючи лямбда, а не запитання назви властивості рядка , бажаючи додати властивості до колекції наступним чином:

var props = new ExportPropertyInfoCollection<JobCard>();
props.Include(model => model.BusinessInstallNumber).Title("Install No").Width(64).KeepZeroPadding(true);
props.Include(model => model.DeviceName).Title("Device").Width(70);
props.Include(model => model.DateRequested).Title("Request Date").Format("{0:dd/MM/yyyy}").Width(83);

Я написав такий Includeметод у методі:

public class PropertyCollection<T>
{
    public void Include(Expression<Func<T, object>> expression)
    {
        var memberExpression = expression.Body as MemberExpression;
        if (memberExpression != null)
        {
            var pes = new ExportPropertyInfoBuilder {Property = new ExportPropertyInfo {Property = memberExpression.Member as PropertyInfo}};
            Properties.Add(pes.Property.Property.Name, pes.Property);
            return pes;
    }

Однак під час запуску коду я виявив, що деякі лямбди давали значення MemberExpression, як очікувалося, але інші - значення UnaryExpression . Мені довелося змінити перший рядок коду на наступний, перш ніж я міг додати всі свої властивості за допомогою лямбда:

var memberExpression = expression.Body as MemberExpression ?? ((UnaryExpression) expression.Body).Operand as MemberExpression;

Усі властивості є "простими" типами, тобто рядок, DateTime, int, bool тощо у бізнес-об'єкті POCO. Вони прикрашені різними атрибутами DataAnnotations .

Що змушує деякі лямбди в моєму прикладі отримувати значення MemberExpression, а інші значення UnaryExpression ? У моєму прикладі перший UnaryExpression знаходиться в третьому рядку, властивість DateTime , але логічні властивості також призводять до UnaryExpressions .


1
Чи може вираз UnaryExpression траплятися у присутності (або "неприсутність") стовпців, що допускають обнулення ?
леппі

@leppie, я підозрюю, що це на ненульованих стовпцях. У моєму прикладі перший UnaryExpression знаходиться в DateTime, де попередні вирази MemberExpression - у рядках. Подальший UnaryExpression знаходиться на закритті.
ProfK

Я трохи досліджу. Я вживав (або, скоріше, зловживав) подібними виразами раніше, і ніколи не мав проблем, тобто це завжди було MemberExpressionіншим випадком, коли мій код міг би провалитися. На якій версії .NET ви працюєте? Я ще не використовую .NET 4.
леппі

Не впевнений, чи це матиме значення, але чи можете ви включити очікуваний тип виразу, який Includeочікується? (включаючи обмеження)
леппі

Відповіді:


63

Здається, я знаю, в чому проблема. Вираз повертає тип object.

Якщо ви зміните це на Expression<Func<T, R>>тип повернення, слід правильно визначити, і UnaryExpression(що, як я вважаю, це якась боксерська операція), це не повинно відбуватися.

Оновлення:

Підпис для Include:

public void Include<T, R>(Expression<Func<T, R>> expression)

1
Вибачте за мою дурість тут, але якою має бути Р? Я не можу зробити його MemberExpression, оскільки MemberExression знаходиться у властивості Body виразу. Я згоден з тим, що UnaryExpression, мабуть, через бокс.
ProfK

4
@ProfK: R просто виводиться, це буде тип властивості, яке повертається. Ви, мабуть, не будете ним користуватися, але можете :)
leppie

2
Здається, я бачу, що відбувається. Оскільки вираз типу return є об'єктом, він поміщається в коробку. З набраним типом повернення цього не відбувається. Дякую @leppie! Довіртесь функціональній людині, яка допоможе тут :-)
ProfK

1
Чудова відповідь. Чи не повинен підпис для Include бути: public void Include <R> (Вираз <Func <T, R >> вираз), оскільки T вже визначено класом PropertyCollection.
Xcalibur

3
@leppie Параметр загального типу T вже визначений на рівні класу, тому слід використовувати інше ім'я параметра параметра, якщо намір інший, або він зайвий
Xcalibur
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.