Как динамически выбирать поля в Linq, когда у типа нет конструктора? - PullRequest
0 голосов
/ 09 апреля 2020

Я пытаюсь создать API, который позволяет запрашивать и возвращать динамические c поля. Однако строка ниже является проблемной c и выдает ошибку времени выполнения:

// new statement "new T()"
var xNew = Expression.New(typeof(T));

Ошибка:

Тип 'izsmmmo.Kurullar.Kurul' не имеет значения по умолчанию Конструктор

Все, что я знаю, это тип interface, поэтому я не могу создать экземпляр. Этот код можно исправить, или мне нужен другой способ создания пользовательского набора выбора?

using System;
using System.Linq;
using System.Linq.Expressions;
using System.Web.Http;
using Composite.Data;

namespace Composite.Controllers
{
    public class TestController : ApiController
    {
        public object Get(string fields = "Onem, KurulAdi")
        {
            using (DataConnection connection = new DataConnection())
            {
                var kurullar = connection.Get<izsmmmo.Kurullar.Kurul>()
                    .Where(k => k.Aktif)
                    //.Select(x => new { KurulAdi = x.KurulAdi, Onem = x.Onem })
                    .Select(CreateNewStatement<izsmmmo.Kurullar.Kurul>(fields))
                    .OrderBy(k => k.Onem);

                return kurullar;
            }
        }

        private Func<T, T> CreateNewStatement<T>(string fields)
        {
            // input parameter "o"
            var xParameter = Expression.Parameter(typeof(T), "o");

            // new statement "new T()"
            var xNew = Expression.New(typeof(T));

            // create initializers
            var bindings = fields.Split(',').Select(o => o.Trim())
                .Select(o =>
                {
                    // property "Field1"
                    var mi = typeof(T).GetProperty(o);

                    // original value "o.Field1"
                    var xOriginal = Expression.Property(xParameter, mi);

                    // set value "Field1 = o.Field1"
                    return Expression.Bind(mi, xOriginal);
                }
            );

            // initialization "new Datax { Field1 = o.Field1, Field2 = o.Field2 }"
            var xInit = Expression.MemberInit(xNew, bindings);

            // expression "o => new Datax { Field1 = o.Field1, Field2 = o.Field2 }"
            var lambda = Expression.Lambda<Func<T, T>>(xInit, xParameter);

            // compile to Func<Datax, Datax>
            return lambda.Compile();
        }
    }
}

1 Ответ

0 голосов
/ 09 апреля 2020

Установка Dynami c Linq Nuget Pack решил проблему:

using System.Linq.Dynamic;

Мне нужно переставить OrderBy непосредственно перед Выбрать , как показано ниже:

public object Get(string fields = "")
{
    const string defaultFields = "Onem, KurulAdi, KurulTanimi";

    fields = String.IsNullOrEmpty(fields) ? defaultFields : fields;

    using (DataConnection connection = new DataConnection())
    {
        var kurullar = connection.Get<izsmmmo.Kurullar.Kurul>()
            .Where(k => k.Aktif)
            .OrderBy(k => k.Onem)
            .Select($"new ({fields})");

        return kurullar;
    }
}

У меня нет проблем с производительностью, поэтому заказывать элементы перед выбором полей мне подходит.

...