鉴于以下两个类:
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));
答案 0 :(得分:4)
您可以这样做,但不能使用通用类型。像这样的泛型类型推断只发生在泛型方法中。使用通用方法声明单独的非 - 泛型类型:
public class XYZ
{
public static XYZ Action<T, TKey> (TKey key, T element)
{
return new XYZ<T>(element);
}
}
编辑:回答问题编辑。
不,你做不到这样的事情:
abc.Accept(Ordering.By(u => u.Id));
问题在于内在表达:
Ordering.By(u => u.Id)
这里u
的类型是什么?它可以是具有Id
属性的任何类。请注意,在查看abc.Accept
之前,C#编译器需要计算出该表达式的类型。即使只有abc.Accept
适用于Ordering<User>
,也会失败。
这里有三个选项:
在泛型类中使用静态方法,显式指定源类型参数,并推断键类型参数:
Ordering<User>.By(u => u.Id)
在非泛型类中使用泛型方法,明确指定两个类型参数:
Ordering.By<User, string>(u => u.Id)
在非泛型类中使用泛型方法,显式指定lambda参数的类型,并让编译器推断键类型参数:
Ordering.By((User u) => u.Id)
显然,所有这些情况都要求您在某处明确指定类型。
如果您通常已经拥有User
的实例(或至少是该类型的变量),则另一个选项是 little 位奇怪是相关的。您可以将其作为一种示例,将被忽略:
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);