0

Is there a way to convertFunc<IQueryable<TD>, IOrderedQueryable<TD>> to Func<IQueryable<TE>, IOrderedQueryable<TE>>.

Let's say I have classes Country and CountryModel.

class CountryModel
{
 public string Name {get;set;}
}

class Country{
 public string Name{get;set;}
}

class Repo{
 public IEnumerable<TD> Get(
            Func<IQueryable<TD>, IOrderedQueryable<TD>> orderBy = null)
{
  IQueryable<TEntityModel> query = CurrentDbSet;
  return orderBy(query).ToList(); // Convert orderBy to TE.
}

}

Using the above method I would pass CountryModel instance. But the query has to happen the entity type Country.

There might be some syntax errors. Apologies for that.

Naresh
  • 2,667
  • 13
  • 44
  • 69

3 Answers3

0
public class Repo
{
    public IEnumerable<TD> Get<TD, TE>(Func<IQueryable<TD>, IOrderedQueryable<TD>> orderBy = null)
    {
        IQueryable<TD> query = new List<TE>().Select(t => Convert<TD, TE>(t)).AsQueryable();
        return orderBy(query).AsEnumerable(); // Convert orderBy to TE.
    }

    public TD Convert<TD, TE>(TE input) where TD : class
    {
        return input as TD;
    } 
}

If your type TE can be casted to the type TD this should work.

You can define explicit or implicit operator in your CountryModel to convert from Country

alexandrekow
  • 1,927
  • 2
  • 22
  • 40
  • thanks for your reply. But this may not work. We are converting the records at first and then applying ordering. Is that first queries the db and get records and applies the ordering? – Naresh Jul 03 '14 at 10:02
0

You may find AutoMapper to be very useful.

public static class MappingExtensions
{
    static MappingExtensions()
    {
        Mapper.CreateMap<CustomAlerts, Domain.Models.CustomAlerts>();
        Mapper.CreateMap<Domain.Models.CustomAlerts, CustomAlerts>();
        //add mappings for each set of objects here. 
        //Remember to map both ways(from x to y and from y to x)
    }

    //map single objects
    public static TDestination Map<TSource, TDestination>(TSource item)
    {
        return Mapper.Map<TSource, TDestination>(item);
    }

    //map collections
    public static IEnumerable<TDestination> Map<TSource, TDestination>(IEnumerable<TSource> item)
    {
        return Mapper.Map<IEnumerable<TSource>, IEnumerable<TDestination>>(item);
    }
}

Then in my code, I can do the following:

var TodayDate = DateTime.Now.AddDays(1);
        var Alerts = DB.CustomAlerts
                       .Where(x => x.EndDate >= TodayDate)
                       .OrderByDescending(x => x.DateCreated)
                       .Skip(((id - 1) * 50))
                       .Take(50);
        return Mapping.MappingExtensions.Map<CustomAlert,Models.CustomAlert>(Alerts).ToList();
Captain Kenpachi
  • 6,960
  • 7
  • 47
  • 68
  • Thanks for your reply. I am not sure whether AutoMapper would be able to map Func<> delegate. I will give a try and update. – Naresh Jul 03 '14 at 10:11
  • I can't say. I've never tried it. I've only ever done it with IQueryable's, which is usually enough for my needs. – Captain Kenpachi Jul 03 '14 at 10:13
  • Sorry, come to think of it, no, Automapper won't do it, but I recall that you can do what these questions' answers suggest: http://stackoverflow.com/questions/5519582/converting-between-func-with-different-of-type-args and http://stackoverflow.com/questions/7138182/convert-funct-string-to-funct-bool – Captain Kenpachi Jul 03 '14 at 10:15
  • Thanks @Juann. But that wasn't much helpful. – Naresh Jul 03 '14 at 12:42
0

Using AutoMapper and wrapping your Func with Expression should help you:

// Initialize AutoMapper
Mapper.Initialize(cfg => 
{ 
    cfg.CreateMap<TE, TD>();
    cfg.CreateMap<TD, TE>();
});

public class Repo
{
    // Wrap Func with Expression
    public IEnumerable<TD> Get(Expression<Func<IQueryable<TD>, IOrderedQueryable<TD>>> orderBy = null)
    {
        var orderByExpr = Mapper.Map<Expression<Func<IQueryable<TE>, IOrderedQueryable<TE>>>>(orderBy);            
        IQueryable<TE> query = CurrentDbSet;

        // Compile expression and execute as function 
        var items = orderByExpr.Compile()(query).ToList();

        // Map back to list of TD
        return Mapper.Map<IEnumerable<TD>>(items);
    }
}