DDD Automapper with Linq Expression

Asked

Viewed 184 times

1

I have a problem with automapper, when I pass a parameter in Linux Express, it seems that it does not make the exchange...

decimal valor = 13;
var model = service.Obter(x => x.DataRegistro == new DateTime(2019, 5, 20));//Esse não funciona
var model = service.Obter(x => x.TipoInformacao == "Teste 002" && x.Realizado == valor);//Esse não funciona
var model = service.Obter(x => x.TipoInformacao == "Teste 002");//Esse funciona sem problemas
var model = service.Obter(x => x.Realizado == valor);//Esse não funciona

Service excerpt:

public DTOPainel Obter(Expression<Func<DTOPainel, bool>> predicate)
    {
        var newPredicate = Mapper.Map<Expression<Func<DTOPainel, bool>>, Expression<Func<Painel, bool>>>(predicate);
        var model = repository.Obter(newPredicate);
        var newModel = Mapper.Map<DTOPainel>(model);
        return newModel;
    }

Error returned by Repository System.Argumentexception: Parameterexpression of type 'Dtopainel' cannot be used for delegate Parameter of type 'Panel'

var newPredicate = Mapper.Map<Expression<Func<DTOPainel, bool>>,Expression<Func<Painel, bool>>>(predicate);

Parameterexpression Type should be 'Panel', but is being passed as 'Dtopainel'

public class AutoMapperConfig
{
    // Versão do AutoMapper: 8.1.0
    public static void RegisterMapping()
    {
        Mapper.Initialize(x =>
        {
            x.AddProfile<DomainToViewModelMappingProfile>();
            x.AddProfile<ViewModelToDomainMappingProfile>();
        });
    }
}

public class DomainToViewModelMappingProfile : Profile
{
    public DomainToViewModelMappingProfile()
    {
        CreateMap<Painel, DTOPainel>().IgnoreAllPropertiesWithAnInaccessibleSetter();
    }
}

public class ViewModelToDomainMappingProfile : Profile
{
    public ViewModelToDomainMappingProfile()
    {
        CreateMap<DTOPainel, Painel>().IgnoreAllPropertiesWithAnInaccessibleSetter();
    }
}

public class Painel
{
    public int Id { get; set; }
    public DateTime DataRegistro { get; set; }
    public String TipoInformacao { get; set; }
    public decimal Meta { get; set; }
    public decimal Realizado { get; set; }
}

public class DTOPainel
{
    public int Id { get; set; }
    public DateTime DataRegistro { get; set; }
    public String TipoInformacao { get; set; }
    public decimal Meta { get; set; }
    public decimal Realizado { get; set; }
}

public interface IRepository<T> where T : class
{
    void Incluir(T model);
    void Alterar(T model);
    void Excluir(Expression<Func<T, bool>> predicate);
    T Obter(params object[] key);
    T Obter(Expression<Func<T, bool>> predicate);
    IEnumerable<T> Listar();
    IEnumerable<T> Listar(Expression<Func<T, bool>> predicate);
    void Commit();
    void Dispose();
}

public interface IRepositoryPainel : IRepository<Painel>
{
}

public class Repository<T> : IRepository<T>, IDisposable where T : class
{
    protected ApplicationDbContext Context;

    public Repository()
    {
        Context = new ApplicationDbContext();
    }

    public virtual void Incluir(T model)
    {
        Context.Set<T>().Add(model);
    }

    public virtual void Alterar(T model)
    {
        Context.Entry(model).State = EntityState.Modified;
    }

    public virtual void Excluir(Expression<Func<T, bool>> predicate)
    {
        Context.Set<T>().Where(predicate).ToList()
            .ForEach(del => Context.Set<T>().Remove(del));
    }

    public virtual T Obter(params object[] key)
    {
        var model = Context.Set<T>().Find(key);
        if (model != null) Context.Entry(model).Reload();
        return model;
    }

    public virtual T Obter(Expression<Func<T, bool>> predicate)
    {
        return Context.Set<T>().AsNoTracking().Where(predicate).FirstOrDefault();
    }

    public virtual IEnumerable<T> Listar()
    {
        return Context.Set<T>().AsNoTracking();
    }

    public virtual IEnumerable<T> Listar(Expression<Func<T, bool>> predicate)
    {
        return Context.Set<T>().Where(predicate).AsNoTracking();
    }

    public virtual void Commit()
    {
        try
        {
            Context.SaveChanges();
        }
        catch (Exception ex)
        {
            throw;
        }
    }

    public virtual void Dispose()
    {
        if (Context != null)
        {
            Context.Dispose();
        }
        GC.SuppressFinalize(this);
    }
}

public class RepositoryPainel : Repository<Painel>, IRepositoryPainel
{
}

public interface IAppService<T> where T : class
{
    void Incluir(T model);
    void Alterar(T model);
    void Excluir(Expression<Func<T, bool>> predicate);
    T Obter(params object[] key);
    T Obter(Expression<Func<T, bool>> predicate);
    IEnumerable<T> Listar();
    IEnumerable<T> Listar(Expression<Func<T, bool>> predicate);
}

public interface IAppServicePainel : IAppService<DTOPainel>
{
}

public class AppServicePainel : IAppServicePainel
{
    private IRepositoryPainel repository;

    public AppServicePainel()
    {
        repository = new RepositoryPainel();
    }

    public void Incluir(DTOPainel model)
    {
        var newModel = Mapper.Map<Painel>(model);
        repository.Incluir(newModel);
        repository.Commit();
        model.Id = newModel.Id;
    }

    public void Alterar(DTOPainel model)
    {
        var oldModel = repository.Obter(model.Id);
        var newModel = Mapper.Map<DTOPainel, Painel>(model, oldModel);
        repository.Alterar(newModel);
        repository.Commit();
    }

    public void Excluir(Expression<Func<DTOPainel, bool>> predicate)
    {
        var newPredicate = Mapper.Map<Expression<Func<DTOPainel, bool>>, Expression<Func<Painel, bool>>>(predicate);
        repository.Excluir(newPredicate);
        repository.Commit();
    }

    public DTOPainel Obter(params object[] key)
    {
        var model = repository.Obter(key);
        var newModel = Mapper.Map<DTOPainel>(model);
        return newModel;
    }

    public DTOPainel Obter(Expression<Func<DTOPainel, bool>> predicate)
    {
        var newPredicate = Mapper.Map<Expression<Func<DTOPainel, bool>>, Expression<Func<Painel, bool>>>(predicate);
        var model = repository.Obter(newPredicate);
        var newModel = Mapper.Map<DTOPainel>(model);
        return newModel;
    }

    public IEnumerable<DTOPainel> Listar()
    {
        var list = repository.Listar();
        var newList = Mapper.Map<IEnumerable<DTOPainel>>(list);
        return newList;
    }

    public IEnumerable<DTOPainel> Listar(Expression<Func<DTOPainel, bool>> predicate)
    {
        var newPredicate = Mapper.Map<Expression<Func<DTOPainel, bool>>, Expression<Func<Painel, bool>>>(predicate);
        var list = repository.Listar(newPredicate);
        var newList = Mapper.Map<IEnumerable<DTOPainel>>(list);
        return newList;
    }
}

class Program
{
    static void Main(string[] args)
    {
        decimal valor = 13;

        //IRepositoryPainel repository = new RepositoryPainel();
        //var model = repository.Obter(x => x.TipoInformacao == "Teste 002" && x.Realizado == valor);
        //var model = repository.Obter(x => x.DataRegistro == new DateTime(2019, 5, 20));

        AutoMapperConfig.RegisterMapping();
        IAppServicePainel service = new AppServicePainel();
        var model = service.Obter(x => x.DataRegistro == new DateTime(2019, 5, 20));//Esse não funciona
        //var model = service.Obter(x => x.TipoInformacao == "Teste 002" && x.Realizado == valor);//Esse não funciona
        //var model = service.Obter(x => x.TipoInformacao == "Teste 002");//Esse funciona
        //var model = service.Obter(x => x.Realizado == valor);//Esse não funciona

        // Erro retornado pelo Repository
        // System.ArgumentException: ParameterExpression of type 'Treinamento.Application.DTO.DTOPainel' 
        // cannot be used for delegate parameter of type 'Treinamento.Domain.Entity.Painel'
        // é como se o automapper não fizesse a conversão
        // var newPredicate = Mapper.Map<Expression<Func<DTOPainel, bool>>, Expression<Func<Painel, bool>>>(predicate);


        Console.WriteLine("Id: " + model.Id);
        Console.WriteLine("TipoInformacao: " + model.TipoInformacao);
        Console.WriteLine("DataRegistro: " + model.DataRegistro.ToString());
        Console.WriteLine("Realizado: " + model.Realizado.ToString());

        Console.ReadKey();
    }
}

2 answers

0

Use the appropriate conversion extension.

AutoMapper.Extensions.ExpressionMapping

Once the version is installed, you will have access to the method:

AutoMapper.Extensions.ExpressionMapping.MapperExtensions.MapExpression()

which accepts two parameters Expression<Func<T, Tresult>, source/Destination.

0

Answer found: https://stackoverflow.com/questions/41692756/convert-type-in-expressionfunct1-bool-to-expressionfunct2-bool-linq-t

var newPredicate = PredicateExtensions.ConvertTypeExpression<DTOPainel, Painel>(predicate.Body);

public static class PredicateExtensions
    {

        public static Expression<Func<OutT, bool>> ConvertTypeExpression<inT, OutT>(Expression expression) where OutT : class
        {
            var param = Expression.Parameter(typeof(OutT), "x");
            var result = new CustomExpVisitor<OutT>(param).Visit(expression);

            Expression<Func<OutT, bool>> lambda = Expression.Lambda<Func<OutT, bool>>(result, new[] { param });

            return lambda;
        }

        private class CustomExpVisitor<T> : ExpressionVisitor
        {
            ParameterExpression _param;

            public CustomExpVisitor(ParameterExpression param)
            {
                _param = param;
            }

            protected override Expression VisitParameter(ParameterExpression node)
            {
                return _param;
            }

            protected override Expression VisitMember(MemberExpression node)
            {
                if (node.Member.MemberType == MemberTypes.Property)
                {
                    MemberExpression memberExpression = null;

                    var memberName = node.Member.Name;
                    var otherMember = typeof(T).GetProperty(memberName);

                    memberExpression = Expression.Property(Visit(node.Expression), otherMember);

                    return memberExpression;
                }
                else
                {
                    return base.VisitMember(node);
                }
            }
        }

    }

Browser other questions tagged

You are not signed in. Login or sign up in order to post.