我有一个模型到视图模型的映射扩展方法库。支持它们是一个基类,有一些常用方法,包括Transform
,下面是:
internal abstract class TransformBase<TOriginal, TConverted>
{
protected abstract Expression<Func<TOriginal, TConverted>> Expression { get; }
public IQueryable<TConverted> Transform(IEnumerable<TOriginal> value)
{
var queryable = value as IQueryable<TOriginal> ?? value.AsQueryable();
return queryable.Select(Expression);
}
我的问题:是否有任何重要原因,除了可以忽略的性能影响之外,我应该避免上面的as IQueryable
演员?例如,我可以改为执行以下操作:
internal abstract class TransformBase<TOriginal, TConverted>
{
protected abstract Expression<Func<TOriginal, TConverted>> Expression { get; }
public IQueryable<TConverted> Transform(IQueryable<TOriginal> value)
{
return value.Select(Expression);
}
public IQueryable<TConverted> Transform(IEnumerable<TOriginal> value)
{
return value.AsQueryable().Select(Expression);
}
...但我宁愿不必在每个依赖类中编写重载。编辑:澄清一下,这是我要避免的一个例子:
public static class TransformCompany
{
private static readonly TransformBase<Organization, CompanyHeader> header = new TransformPrecompiled<Organization, CompanyHeader>(
company => new CompanyHeader
{
Name = company.Name,
});
public static IQueryable<CompanyHeader> AsHeaders(this IQueryable<Organization> companies)
{
return header.Transform(companies);
}
// Note I have to include this capability in each of my dependent classes
// Worse is the possibility that someone may accidentally implement
// only IEnumerable for a future model transformation,
// causing a hidden data performance problem
public static IQueryable<CompanyHeader> AsHeaders(this IEnumerable<Organization> companies)
{
return header.Transform(companies);
}
答案 0 :(得分:1)
Queryable.AsQueryable Method (IEnumerable)
如果源的类型实现了IQueryable, AsQueryable(IEnumerable)直接返回它。否则,它返回一个 IQueryable通过调用等效查询来执行查询 Enumerable中的operator方法,而不是Queryable中的方法。
而不是将您的Transform
方法简化为
return value.AsQueryable().Select(Expression);
答案 1 :(得分:1)
我认为您不需要IEnumerable<T>
和IQueryable<T>
的单独扩展名,因为IQueryable<T>
继承自IEnumerable<T>
,您也不需要演员。
查看referencesource,AsQueryable()
实际上会为您检查:
public static IQueryable<TElement> AsQueryable<TElement>(this IEnumerable<TElement> source)
{
if (source == null)
throw Error.ArgumentNull("source");
if (source is IQueryable<TElement>)
return (IQueryable<TElement>)source;
return new EnumerableQuery<TElement>(source);
}
因此,以下内容应该对您没有任何影响:
internal abstract class TransformBase<TOriginal, TConverted>
{
protected abstract Expression<Func<TOriginal, TConverted>> Expression { get; }
public IQueryable<TConverted> Transform(IEnumerable<TOriginal> value)
{
return value.AsQueryable().Select(Expression);
}
}
public static class TransformCompany
{
public static IQueryable<CompanyHeader> AsHeaders(this IEnumerable<Organization> companies)
{
return header.Transform(companies);
}
}