using System.Collections.Generic;
using System.Linq.Dynamic.Core;
using System.Linq.Expressions;
using AutoMapper.Extensions.ExpressionMapping;
using AutoMapper.QueryableExtensions;
public static class ExtensionMethods
public static T DeepCopy<T>(this T self)
var serialized = JsonSerializer.Serialize<T>(self);
return JsonSerializer.Deserialize<T>(serialized);
public virtual DateTime DateCreated { get; set; } = DateTime.MinValue;
public virtual DateTime DateUpdated { get; set; } = DateTime.MinValue;
public virtual Guid CreateOperatorId { get; set; } = Guid.Empty;
public virtual Guid UpdateOperatorId { get; set; } = Guid.Empty;
public class AttributeOMS
public virtual string Identity { get; set; } = string.Empty;
public virtual string Entity { get; set; } = string.Empty;
public virtual string Description { get; set; } = string.Empty;
public virtual Audit Audit { get; set; } = null!;
public virtual ICollection<AttributeDescription> Descriptions { get; set; } = new List<AttributeDescription>();
public class AttributeDescriptionKey
public virtual string AttributeId { get; set; } = string.Empty;
public virtual string LanguageId { get; set; } = string.Empty;
public override bool Equals(object obj)
if (obj == null || GetType() != obj.GetType()) return false;
AttributeDescriptionKey other = (AttributeDescriptionKey)obj;
return AttributeId.Equals(other.AttributeId, StringComparison.CurrentCultureIgnoreCase) && LanguageId.Equals(other.LanguageId, StringComparison.CurrentCultureIgnoreCase);
public override int GetHashCode()
return HashCode.Combine(AttributeId, LanguageId);
public class AttributeDescription
public virtual AttributeDescriptionKey Identity { get; set; } = null;
public virtual string Description { get; set; } = string.Empty;
public virtual Audit Audit { get; set; } = null!;
public DateTime DateCreated { get; set; }
public DateTime DateUpdated { get; set; }
public Guid IdCreateOperator { get; set; }
public Guid IdUpdateOperator { get; set; }
public string UsernameCreateOperator { get; set; }
public string UsernameUpdateOperator { get; set; }
public class AttributeBaseDto : AuditDto
public string Id { get; set; }
public string Entity { get; set; }
public string Description { get; set; }
public class AttributeDto : AttributeBaseDto
public IList<AttributeDescriptionDto> Descriptions { get; set; }
public class AttributeDescriptionDto : AuditDto
public string IdLanguage { get; set; }
public string Description { get; set; }
public static void Main()
var config = new MapperConfiguration(cfg =>
cfg.AddExpressionMapping();
cfg.CreateMap<AttributeOMS, AttributeDto>()
.ForMember(dest => dest.Id, opt => opt.MapFrom(src => src.Identity));
cfg.CreateMap<AttributeDto, AttributeOMS>()
.ForMember(dest => dest.Identity, opt => opt.MapFrom(src => src.Id));
cfg.CreateMap<AttributeDescriptionDto, AttributeDescription>();
var mapper = config.CreateMapper();
var attributeOMS = new AttributeOMS
Description = "Some description",
DateCreated = DateTime.Now,
DateUpdated = DateTime.Now,
CreateOperatorId = Guid.NewGuid(),
UpdateOperatorId = Guid.NewGuid()
Descriptions = new List<AttributeDescription>
Identity = new AttributeDescriptionKey
AttributeId = "AttributeId1",
LanguageId = "LanguageId1"
Description = "Description1",
DateCreated = DateTime.Now,
DateUpdated = DateTime.Now,
CreateOperatorId = Guid.NewGuid(),
UpdateOperatorId = Guid.NewGuid()
Identity = new AttributeDescriptionKey
AttributeId = "AttributeId2",
LanguageId = "LanguageId2"
Description = "Description2",
DateCreated = DateTime.Now,
DateUpdated = DateTime.Now,
CreateOperatorId = Guid.NewGuid(),
UpdateOperatorId = Guid.NewGuid()
var attributeOMS2 = attributeOMS.DeepCopy();
attributeOMS2.Identity = "AA01";
var attributes = new AttributeOMS[] { attributeOMS, attributeOMS2 };
Expression<Func<AttributeOMS, bool>> expression = x => (x.Entity == "SomeEntity" && x.Description.Contains("description") || x.Identity == "AA00");
var expressionString = "x =>" + expression.Body.ToString();
Console.WriteLine(expressionString);
Expression<Func<AttributeOMS, object>> expressionOrder = x => x.Identity;
var expressionOrderString = "x =>" + expressionOrder.Body.ToString() + " asc";
Console.WriteLine(expressionOrderString);
var filteredAttributes = attributes.AsQueryable().Where(expressionString).OrderBy(expressionOrderString);
foreach (var attribute in filteredAttributes)
Console.WriteLine(attribute.Identity + " " + attribute.Description);
AttributeDto attributeDto = new AttributeDto
Description = "Some description",
DateCreated = DateTime.Now,
DateUpdated = DateTime.Now,
IdCreateOperator = Guid.NewGuid(),
IdUpdateOperator = Guid.NewGuid(),
UsernameCreateOperator = "User1",
UsernameUpdateOperator = "User2",
Descriptions = new List<AttributeDescriptionDto>
new AttributeDescriptionDto
IdLanguage = "LanguageId1",
Description = "Description1",
DateCreated = DateTime.Now,
DateUpdated = DateTime.Now,
IdCreateOperator = Guid.NewGuid(),
IdUpdateOperator = Guid.NewGuid(),
UsernameCreateOperator = "User1",
UsernameUpdateOperator = "User2"
new AttributeDescriptionDto
IdLanguage = "LanguageId2",
Description = "Description2",
DateCreated = DateTime.Now,
DateUpdated = DateTime.Now,
IdCreateOperator = Guid.NewGuid(),
IdUpdateOperator = Guid.NewGuid(),
UsernameCreateOperator = "User3",
UsernameUpdateOperator = "User4"
var attributeDto2 = attributeDto.DeepCopy();
attributeDto2.Id = "AA01";
var attributesDTO = new AttributeDto[] { attributeDto, attributeDto2 };
Expression<Func<AttributeDto, bool>> expressionDTO = x => (x.Entity == "SomeEntity" && x.Description.Contains("description") || x.Id == "AA00");
var expressionStringDTO = "x =>" + expressionDTO.Body.ToString();
Console.WriteLine(expressionStringDTO);
Expression<Func<AttributeDto, object>> expressionOrderDTO = x => x.Id;
var expressionOrderStringDTO = "x =>" + expressionOrderDTO.Body.ToString();
Console.WriteLine(expressionOrderStringDTO);
var filteredAttributesDTO = attributesDTO.AsQueryable().Where(expressionStringDTO).OrderBy(expressionOrderStringDTO);
foreach (var attribute in filteredAttributesDTO)
Console.WriteLine(attribute.Id + " " + attribute.Description);
var whereClause = DynamicExpressionParser.ParseLambda<AttributeDto, bool>(ParsingConfig.Default, true, expressionStringDTO);
var orderClause = DynamicExpressionParser.ParseLambda<AttributeDto, object>(ParsingConfig.Default, true, expressionOrderStringDTO);
var expressionDTOOMS = mapper.Map<Expression<Func<AttributeOMS, bool>>>(whereClause);
var expressionStringDTOOMS = "Param_0 =>" + expressionDTOOMS.Body.ToString();
Console.WriteLine(expressionStringDTOOMS);
var expressionOrderDTOOMS = mapper.Map<Expression<Func<AttributeOMS, object>>>(orderClause);
var expressionOrderStringDTOOMS = "Param_0 =>" + expressionOrderDTOOMS.Body.ToString() + " asc";
Console.WriteLine(expressionOrderStringDTOOMS);
var filteredAttributesDTOOMS = attributes.AsQueryable().Where(expressionStringDTOOMS);
foreach (var attribute in filteredAttributesDTOOMS)
Console.WriteLine(attribute.Identity + " " + attribute.Description);