2016-04-28 39 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); 
}