2016-04-28 71 views
1

我有這樣一個功能下加載使用LinqToSql數據庫表,並返回轉化爲我的自定義模型類的條目列表:需要幫助簡化使用泛型在C#方法

public List<AreaModel> LoadListOfAreaModels(Boolean includeDeleted = false) 
    { 
     using (LinqToSqlDataContext dc = new LinqToSqlDataContext()) 
     { 
      IQueryable<Areas> filtered = includeDeleted 
       ? dc.Areas.Where((c) => !c.DataRowDeleted) 
       : dc.Areas; 
      return filtered.Select((c) => AreaModel.ModelFactoryFromLinq(c)).ToList(); 
     } 
    } 

現在我有相當多的表格,並且都必須以相同的方式加載和轉換。

我能以某種方式避免輸入此功能十幾次,只是將AreaModelAreas更改爲例如TownModelTowns通過使用通用函數?

我已經試過這個,但失敗了,因爲我找不到調用靜態類方法的方法,如果我只有它的泛型類型參數。

進一步信息:(!不包含靜態工廠方法,我需要調用,雖然)所有XxxModel類具有共同的超ModelBase,所有的LINQ表類(如AreasTowns)實現公共接口ILinqClass

關於如何實現這個最優雅的方式的任何想法?


通過knittl的回答啓發,我想出了這個解決方案:

public List<TModel> LoadListOfModels<TLinq, TModel>(
     Func<TLinq, bool> filter, 
     Func<TLinq, TModel> modelFactory 
     ) 
     where TLinq : class, ILinqClass 
     where TModel : ModelBase 
    { 
     using (LinqToSqlDataContext dc = new LinqToSqlDataContext()) 
     { 
      return dc.GetTable<TLinq>() 
       .Where(filter) 
       .Select(modelFactory) 
       .ToList(); 
     } 
    } 
+0

是'DataRowDeleted'在ModelBase中定義? – Lee

+0

@Lee是的,'DataRowDeleted'它是'ModelBase'的一個接口的一部分implements –

+0

你提到的問題是AreaModel是一個靜態類。你爲什麼不試着讓你的AreaModel,TownModel成爲一個非靜態類?然後他們可以用一個方法ModelFactoryFromLinq實現一個接口,就像IModelFactory一樣,然後你可以將一個實現傳遞給你的LoadList方法的接口。 –

回答

2

您應該能夠通過代表/ funcs中:

public List<TModel> LoadListOfModels<TDbModel, TModel>(
    Func<LinqToSqlDataContext, TDbModel> modelSelector, 
    Func<TDbModel, bool> isDeleted, 
    Func<TDbModel, TModel> modelFactory, 
    bool includeDeleted = false) 
{ 
    using (LinqToSqlDataContext dc = new LinqToSqlDataContext()) 
    { 
     var models = modelSelector(dc); 
     var filtered = includeDeleted 
      ? models.Where(c => !isDeleted(c)) 
      : models; 

     return filtered.Select(modelFactory).ToList(); 
    } 
} 

對於Area通話如下:

LoadListOfModels(
    dc => dc.Areas, 
    c => c.DataRowDeleted, 
    Area.ModelFactoryFromLinq, 
    includeDeleted); 

Town

LoadListOfModels(
    dc => dc.Towns, 
    c => c.DataRowDeleted, 
    Town.ModelFactoryFromLinq, 
    includeDeleted); 

你甚至可能能夠擺脫includeDeleted參數。只需通過一個過濾器功能Func<TDbModel, bool> filter

return modelsSelector(dc) 
    .Where(filter) 
    .Select(modelFactory) 
    .ToList(); 

電話:

LoadListOfModels(dc => dc.Areas, c => true, Area.ModelFactoryFromLinq); 
LoadListOfModels(dc => dc.Areas, c => !c.DataRowDeleted, Area.ModelFactoryFromLinq); 
+0

謝謝,我設法擺脫了modelSelector參數,請參閱我編輯的問題以獲得最終方法。 –

1

試試這個辦法:

public abstract class BaseClass<TModel> where TModel : class 
{ 
    public bool DataRowDeleted { get; set; } 
    public abstract TModel ModelFactoryFromLinq(); 
} 

public class Area : BaseClass<AreaModel> 
{ 
    public override AreaModel ModelFactoryFromLinq() 
    { 
     return new AreaModel(); 
    } 
} 

public static List<TModel> LoadListOfAreaModels<TContext, TModel>(bool includeDeleted = false) 
    where TContext : BaseClass<TModel>, new() 
    where TModel : class 
{ 
    using (var dc = new LinqToSqlDataContext()) 
    { 
     IQueryable<TContext> filtered = includeDeleted 
      ? dc.GetTable<TContext>().Where((c) => !c.DataRowDeleted) 
      : dc.GetTable<TContext>(); 
     return filtered.Select((c) => c.ModelFactoryFromLinq()).ToList(); 
    } 
} 

實現:

List<AreaModel> result = SomeClassName.LoadListOfAreaModels<Area, AreaModel>(); 
0

如果DataRowDeleted定義在ModelBase你應該能夠做到:

public static IQueryable<TModel> LoadListOfQuery<T, TModel>(IQueryable<T> source, Expression<Func<T, TModel>> selector, bool includeDeleted = false) where T : ModelBase { 
    IQueryable<T> filtered = includeDeleted ? source : source.Where(s => !s.DataRowDeleted); 
    return filtered.Select(selector); 
} 

然後添加一個函數來計算給定語境的查詢:

public static List<T> ExecList(Func<LinqToSqlDataContext, IQueryable<T>> qf) 
{ 
    using(var c = new LinqToSqlDataContext()) 
    { 
     var q = qf(c); 
     return q.ToList(); 
    } 
} 

然後,你可以這樣做:

public List<AreaModel> LoadListOfAreaModels(bool includeDeleted = false) 
{ 
    ExecList(c => LoadListOfQuery(c.Areas, a => AreaModel.ModelFactoryFromLinq(a), includeDeleted); 
}