3

Related Topics:

Create Expression<Func<T, TKey>> dynamically

I searched on the internet but all samples explain Expression<Func<. How I can dynamically create a Func<T, TKey> from T?

Thanks


Edit 1)

The T type in my code determine in runtime and for example I want to sort my list with Name. Now How I can create this : Func<T, TKey> = o=>o.Name;


Edit 2)

Please consider this:

public abstract class MyClass<T> where T : class
{
    public virtual List<T> GetAll(Expression<Func<T, bool>> exp, string orderByProperty)
    {
         repository.Get(exp).OrderBy(?);
    }
}

The problem is create a Func<T, TKey> for using in OrderBy argument. How can I sort the list using Name property?

Thanks

Arian
  • 12,793
  • 66
  • 176
  • 300
  • 1
    Please edit your question to elaborate on "dynamic". What are you trying to do? What have you tried? What didn't work as expected? – Progman Apr 22 '19 at 11:06
  • 2
    This sounds like a [XY problem](https://meta.stackexchange.com/questions/66377/what-is-the-xy-problem). Can you explain in detail what you want to do by creating this a `Func<>` object? Where do you need to provide this information? What do you want to do? How have you planned to do what you are trying to do? Please extend the description/problem in your question. – Progman Apr 22 '19 at 19:39
  • Sounds like you'd need to find the right `PropertyInfo`, get the suitable getter method from that, and call `Delegate.CreateDelegate`. If you could provide a [mcve] of what you're trying to achieve, it would be easier to check that and provide an answer. – Jon Skeet Apr 27 '19 at 07:49
  • @Arian you still lack a [mcve]. That last edit does not help on its own. On its own it wont compile, but the assumption is that it is part of a generic class. But that is an assumption, which is not helpful in providing you with relevant solutions. – Nkosi Apr 27 '19 at 12:14
  • @Nkosi I updated my code again. I really don't know what to update – Arian Apr 27 '19 at 12:35
  • 1
    How the method in question knows which property to order by? e.g. where `Name` (and not `FooBar`) comes from? Neither the class nor the method has indication for that. Also if it is a `string`, there are several solutions on SO - https://stackoverflow.com/questions/39908403/how-to-use-a-string-to-create-a-ef-order-by-expression/39916384#39916384, https://stackoverflow.com/questions/8398453/linq-order-by-when-column-name-is-dynamic-and-pass-as-a-string-to-a-function etc. – Ivan Stoev Apr 27 '19 at 13:30
  • I agree with @IvanStoev here. And the linked suggestions should provide you with enough of a foundation to achieve what you are trying to do given the current edits to the question. – Nkosi Apr 27 '19 at 13:54
  • @Arian for clarification, will `string orderByProperty` represent a single column or multiple columns? – Nkosi Apr 27 '19 at 13:55
  • It's somewhat clearer, but an actual [mcve] would be better - what you've got, but with sample data and how you expect to use it, along with the results. – Jon Skeet Apr 27 '19 at 16:09

2 Answers2

2

Given the definition of the abstract class, you would need to include the key are part of the generic arguments in order to be able to use it.

Simple example of passing the order by function.

public abstract class MyClass<T, TKey> where T : class {
    public virtual List<T> GetAll(
        Expression<Func<T, bool>> exp, 
        Func<T, TKey> keySelector = null
    ) {
        var query = repository.Get(exp);

        if(orderBy != null) {
            return query.OrderBy(keySelector).ToList();

        return query.ToList();
    }
}

You could then have a derived version of the class with a default key type

For example, the following uses a string, but that could just as easily been an int, Guid, etc..

public abstract class MyClass<T> : MyClass<T, string> where T : class {

}

But bottom line is you need to know the order by type in order to be able to use it.

...GetAll(_ => _.SomeProperty == someValue, o => o.Name);
Nkosi
  • 235,767
  • 35
  • 427
  • 472
  • It's impossible because I have another methods that they should sort their records using other columns – Arian Apr 27 '19 at 12:53
  • @Arian you see exactly what I mean by not having a [mcve]. How were we suppose to know that? This suggestion was provided based on the given information. – Nkosi Apr 27 '19 at 13:02
0

If you want to go dynamic all the way, you can just use System.Linq.Dynamic.Core

class SomeClass
{
    public int SomeValue { get; set; }

    public int X { get; set; }
}

public class MyClass
{
    public static List<T> GetAll<T>(string predicate, string orderByProperty)
    {
        var repository = new List<SomeClass>() {
            new SomeClass{SomeValue = 1, X = 12 },
            new SomeClass{SomeValue = 2, X = 99 },
            new SomeClass{SomeValue = 3, X = 55 }
        }.AsQueryable();

        return repository.Where(predicate).OrderBy(orderByProperty).ToDynamicList<T>();
    }
}

void Main()
{
    var result = MyClass.GetAll<SomeClass>("SomeValue > 1", "X");
    result.Dump();
}
Stef Heyenrath
  • 9,335
  • 12
  • 66
  • 121