Я добавил ответ, который решил мою проблему. Надеюсь, это поможет вам понять, что я пытался решить. Спасибо за попытку помочь.
тоящее время у нас есть пакет, который генерирует linq select динамически из полей из строки. Он хорошо работает с плоскими свойствами, но не предназначен для работы с вложенными полями, такими как someObj.NestedObj.SomeField.
Наш текущий код работает как показано ниже в методе обслуживания:
_context.Shipments
.Where(s => s.Id == request.Id) // it does not matter just an example
.Select(request.Fields)
.ToPage(request); // ToPage extension comes from a nuget package
Параметр «fields» объекта запроса - это просто строка, разделенная запятыми, включая свойства объекта Shipment.
Я произвел некоторый рефакторинг в Shipment, я сгруппировал некоторые поля в новый класс с именем Address и добавил его в Shipment, как показано ниже:
// before refactoring
class Shipment {
// other fields...
public string SenderAddress;
public string SenderCityName;
public string SenderCityId;
public string RecipientAddress;
public string CityName;
public string CityId;
}
// after refactoring
class Shipment {
// other fields...
public Address Sender;
public Address Recipient;
}
class Address {
public string AddressText;
public string CityName;
public string CityId;
}
Ради текущего отображения базы данных я добавил соответствующие отображения как:
public class ShipmentMap : DataEntityTypeConfiguration<Shipment>
{
public ShipmentMap()
{
ToTable("Shipments");
// other property mappings
Property(s => s.Recipient.AddressText).HasMaxLength(1100).HasColumnName("RecipientAddress");
Property(s => s.Recipient.CityName).HasMaxLength(100).HasColumnName("CityName");
Property(s => s.Recipient.CityId).IsOptional().HasColumnName("CityId");
Property(s => s.Sender.AddressText).HasMaxLength(1100).HasColumnName("SenderAddress");
Property(s => s.Sender.CityName).HasMaxLength(100).HasColumnName("SenderCityName");
Property(s => s.Sender.CityId).IsOptional().HasColumnName("SenderCityId");
}
}
DataEntityTypeConfiguration приходит из пакетов nuget как:
public abstract class DataEntityTypeConfiguration<T> : EntityTypeConfiguration<T> where T : class
{
protected virtual void PostInitialize();
}
Итак, моя проблема с select (fields) не работает, когда fields = "Recipient.CityId".
Как я могу динамически генерировать linq для выбора с вложенными полями?
Я попробовал ниже, используяLINQ: динамический выбор Но это не работает.
// assume that request.Fields= "Recipient.CityId"
// in the service method
List<Shipment> x = _context.Shipments
.Where(s => s.Id == request.Id)
.Select(CreateNewStatement(request.Fields))
.ToList();
// I tried to generate select for linq here
Func<Shipment, Shipment> CreateNewStatement(string fields)
{
// input parameter "o"
var xParameter = Expression.Parameter( typeof( Shipment ), "o" );
// new statement "new Data()"
var xNew = Expression.New( typeof( Shipment ) );
// create initializers
var bindings = fields.Split( ',' ).Select( o => o.Trim() )
.Select(o =>
{
string[] nestedProps = o.Split('.');
Expression mbr = xParameter;
foreach (var prop in nestedProps)
mbr = Expression.PropertyOrField(mbr, prop);
// property "Field1"
PropertyInfo mi = typeof( Shipment ).GetProperty( ((MemberExpression)mbr).Member.Name );
//
// original value "o.Field1"
var xOriginal = Expression.Property( xParameter, mi );
MemberBinding bnd = Expression.Bind( mi, xOriginal );
return bnd;
});
// initialization "new Data { Field1 = o.Field1, Field2 = o.Field2 }"
var xInit = Expression.MemberInit( xNew, bindings );
// expression "o => new Data { Field1 = o.Field1, Field2 = o.Field2 }"
var lambda = Expression.Lambda<Func<Shipment,Shipment>>( xInit, xParameter );
// compile to Func<Data, Data>
return lambda.Compile();
}
Он выдает исключение, потому что mbr становится CityId после цикла, а "mi" равно нулю, потому что в отгрузке нет поля CityId. Что мне здесь не хватает? Как я могу создать динамический выбор для данной строки с вложенными свойствами?
ОБНОВИТЬ :
Я нашел решение и добавил его в качестве ответа, а также создал Github Gist для решения:
https://gist.github.com/mstrYoda/663789375b0df23e2662a53bebaf2c7c