在泛型方法中仅设置第二个参数类型
Set only second argument type in generic method
我必须创建一种方法来从具有指定类型的集合中选择第一个属性。
我创建了这样的方法(为简洁起见,我删除了一些部分):
public static IQueryable<TResult> SelectFirstPropertyWithType<T, TResult>(this IQueryable<T> source)
{
// Get the first property which has the TResult type
var propertyName = typeof(T).GetProperties()
.Where(x => x.PropertyType == typeof(TResult))
.Select(x => x.Name)
.FirstOrDefault();
var parameter = Expression.Parameter(typeof(T));
var body = Expression.Convert(Expression.PropertyOrField(parameter, propertyName), typeof(TResult));
var expression = Expression.Lambda<Func<T, TResult>>(body, parameter);
return source.Select(expression);
}
我可以将此方法称为:
List<Person> personList = new List<Person>();
// .. initialize personList
personList.AsQueryable()
.SelectFirstPropertyWithType<Person, int>()
.ToList();
一切正常。
但是,我不想将第一个参数类型设置为 Person
,因为编译器可以从集合的源中推断出该参数类型。有没有办法像这样调用方法:
.SelectFirstPropertyWithType<int>()
问题是我的方法中需要 T
参数,我不想在运行时使用反射创建 Func
。
谢谢。
没有。编译器应该能够推断出 all 类型参数。如果不能,它将要求您指定所有这些。
编译器无法告诉您它可以推断出第一个或第二个,因此它没有非确定性编译应用程序,而是中断了。
C# 泛型不允许您指定类型参数的子集。全有或全无。
解决这个问题的方法是编写流畅的界面。您将此操作分解为一系列方法。
public class FirstPropertyWithTypeSelector<T>
{
private readonly IQueryable<T> _source;
public FirstPropertyWithTypeSelector(IQueryable<T> source)
{
_source = source;
}
public IQueryable<TResult> OfType<TResult>()
{
// Get the first property which has the TResult type
var propertyName = typeof(T).GetProperties()
.Where(x => x.PropertyType == typeof(TResult))
.Select(x => x.Name)
.FirstOrDefault();
var parameter = Expression.Parameter(typeof(T));
var body = Expression.Convert(Expression.PropertyOrField(parameter, propertyName), typeof(TResult));
var expression = Expression.Lambda<Func<T, TResult>>(body, parameter);
return _source.Select(expression);
}
}
public static FirstPropertyWithTypeSelector<T> SelectFirstProperty(this IQueryable<T> source)
{
return new FirstPropertyWithTypeSelector<T>(source);
}
现在您可以拨打:
personList.AsQueryable()
.SelectFirstProperty().OfType<int>()
.ToList();
我必须创建一种方法来从具有指定类型的集合中选择第一个属性。
我创建了这样的方法(为简洁起见,我删除了一些部分):
public static IQueryable<TResult> SelectFirstPropertyWithType<T, TResult>(this IQueryable<T> source)
{
// Get the first property which has the TResult type
var propertyName = typeof(T).GetProperties()
.Where(x => x.PropertyType == typeof(TResult))
.Select(x => x.Name)
.FirstOrDefault();
var parameter = Expression.Parameter(typeof(T));
var body = Expression.Convert(Expression.PropertyOrField(parameter, propertyName), typeof(TResult));
var expression = Expression.Lambda<Func<T, TResult>>(body, parameter);
return source.Select(expression);
}
我可以将此方法称为:
List<Person> personList = new List<Person>();
// .. initialize personList
personList.AsQueryable()
.SelectFirstPropertyWithType<Person, int>()
.ToList();
一切正常。
但是,我不想将第一个参数类型设置为 Person
,因为编译器可以从集合的源中推断出该参数类型。有没有办法像这样调用方法:
.SelectFirstPropertyWithType<int>()
问题是我的方法中需要 T
参数,我不想在运行时使用反射创建 Func
。
谢谢。
没有。编译器应该能够推断出 all 类型参数。如果不能,它将要求您指定所有这些。
编译器无法告诉您它可以推断出第一个或第二个,因此它没有非确定性编译应用程序,而是中断了。
C# 泛型不允许您指定类型参数的子集。全有或全无。
解决这个问题的方法是编写流畅的界面。您将此操作分解为一系列方法。
public class FirstPropertyWithTypeSelector<T>
{
private readonly IQueryable<T> _source;
public FirstPropertyWithTypeSelector(IQueryable<T> source)
{
_source = source;
}
public IQueryable<TResult> OfType<TResult>()
{
// Get the first property which has the TResult type
var propertyName = typeof(T).GetProperties()
.Where(x => x.PropertyType == typeof(TResult))
.Select(x => x.Name)
.FirstOrDefault();
var parameter = Expression.Parameter(typeof(T));
var body = Expression.Convert(Expression.PropertyOrField(parameter, propertyName), typeof(TResult));
var expression = Expression.Lambda<Func<T, TResult>>(body, parameter);
return _source.Select(expression);
}
}
public static FirstPropertyWithTypeSelector<T> SelectFirstProperty(this IQueryable<T> source)
{
return new FirstPropertyWithTypeSelector<T>(source);
}
现在您可以拨打:
personList.AsQueryable()
.SelectFirstProperty().OfType<int>()
.ToList();