2010-06-28 3 views
0

Учитывая следующие два класса:Вывод типа класса из статического метода/вызывающего?

public class ABC 
{ 
    public void Accept(Ordering<User> xyz) 
    { 
     // Do stuff with xyz... 
    } 
} 

public class Ordering<TEntity> 
     where TEntity : class 
{ 
    private readonly Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> Transform; 

    private Ordering(Func<IQueryable<TEntity>, IOrderedQueryable<TEntity>> transform) 
    { 
     this.Transform = transform; 
    } 

    public static Ordering<TEntity> By<TKey>(Expression<Func<TEntity, TKey>> expression) 
    { 
     return new Ordering<TEntity>(query => query.OrderBy(expression)); 
    } 

    public static Ordering<TEntity> ByDescending<TKey>(Expression<Func<TEntity, TKey>> expression) 
    { 
     return new Ordering<TEntity>(query => query.OrderByDescending(expression)); 
    } 

    public Ordering<TEntity> ThenBy<TKey>(Expression<Func<TEntity, TKey>> expression) 
    { 
     return new Ordering<TEntity>(query => this.Transform(query).ThenBy(expression)); 
    } 

    public Ordering<TEntity> ThenByDescending<TKey>(Expression<Func<TEntity, TKey>> expression) 
    { 
     return new Ordering<TEntity>(query => this.Transform(query).ThenByDescending(expression)); 
    } 

    public IOrderedQueryable<TEntity> Apply(IQueryable<TEntity> query) 
    { 
     return Transform(query); 
    } 

} 

Используется следующим образом:

ABC abc = new ABC(); 
abc.Accept(Ordering<User>.By(u => u.Id)); 

Есть ли способ, чтобы определить тип T так:

abc.Accept(Ordering.By(u => u.Id)); 

ответ

4

Вы можете делайте это, но не в родовом типе. Вывод общего типа, как это происходит только для общих методов. Объявите отдельный не -генерической типа, с общим способом:

public class XYZ 
{ 
    public static XYZ Action<T, TKey> (TKey key, T element) 
    { 
     return new XYZ<T>(element); 
    } 
} 

EDIT: В ответ на вопрос редактирования.

Нет, вы не можете сделать что-то вроде этого:

abc.Accept(Ordering.By(u => u.Id)); 

Проблема является внутреннее выражение:

Ordering.By(u => u.Id) 

Что тип u здесь? Это может быть любой класс с свойством Id. Обратите внимание, что компилятору C# необходимо будет выработать тип этого выражения до, он выглядит abc.Accept. Даже если abc.Acceptтолько работал на Ordering<User>, это не получится.

Есть три варианта здесь:

  • Используйте статический метод в универсальном классе, указав тип источника аргумента явно, а выводя ключевой аргумент типа:

    Ordering<User>.By(u => u.Id) 
    
  • Используйте общий метод в неэквивалентном классе, явно указывая оба аргумента типа:

    Ordering.By<User, string>(u => u.Id) 
    
  • Используйте универсальный метод в необщего класс, указав тип параметра лямбда в явном виде, и позволяя компилятору вывести тип ключа аргумент:

    Ordering.By((User u) => u.Id) 
    

Очевидно, что во всех этих случаях требует от вас чтобы указать тип явно где-то.

Еще один вариант, который является немного немного странно уместной, если у Вас есть, как правило, уже есть экземпляр User (или, по крайней мере переменной этого типа). Вы можете использовать это как своего рода пример, который игнорируется:

public static Ordering<T> By<T,TKey>(Expression<Func<T, TKey>> func, T example) 
{ 
    return By<T, TKey>(func); 
} 
... 

Ordering.By(u => u.Id, dummyUser); 
+0

Я просто это понял. Я просто понял, что мне нужно обновить свой вопрос, чтобы воспроизвести мою проблему. См. Мое редактирование выше. – TheCloudlessSky

+0

Проблема в том, что я фактически передаю выражение Expression > в качестве параметра. – TheCloudlessSky

+0

@TheCloudlessSky: Боюсь, не видя больше деталей, трудно понять, что рекомендовать. –

Смежные вопросы