2015-07-05 22 views
1

我有一個model-to-viewmodel映射擴展方法的庫。支持他們與幾個常用的方法一個基類,包括Transform,如下所示:任何避免`作爲IQueryable`的重要原因?

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); 
    } 
+1

不知道你的最後一句話是什麼意思。這兩套代碼對我來說都是一樣的,除了第二套代碼更具可讀性。 – Rhumborl

+0

我已經添加了一個例子。 – shannon

+0

請注意,理解澄清並不是嚴格需要回答我的問題。我的意思並不是以被動攻擊的方式,而是試圖通過包含這些新信息來避免使問題脫軌。 – shannon

回答

1

的我會說,你不需要爲IEnumerable<T>和獨立的擴展從IEnumerable<T>IQueryable<T>IQueryable<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); 
    } 
} 
1

Queryable.AsQueryable Method (IEnumerable)

如果源類型實現的IQueryable, AsQueryable已(IEnumerable的)直接返回。否則,它會返回一個 IQueryable,它通過在Enumerable中調用等效查詢 運算符方法(而不是Queryable中的那些運算符方法)來執行查詢。

相反鑄造您簡化Transform方法

return value.AsQueryable().Select(Expression); 
+0

謝謝。我選擇了@Rhumborl的答案,因爲他還就我的主要問題發表了自己的看法,我不需要任何理由單獨的方法簽名。 – shannon