我有下面这样的函数,它使用LinqToSql加载数据库表,并返回转换为我的自定义模型类的条目列表:
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();
}
}
现在我有很多表,所有表都必须以相同的方式加载和转换。
我可以以某种方式避免输入此功能十几次,只需将AreaModel
和Areas
更改为例如TownModel
和Towns
使用通用函数?
我已经尝试了这个,但失败了,因为如果我只有它的泛型类型参数,我就找不到调用静态类方法的方法。
更多信息:所有XxxModel
类都有公共超类ModelBase
(不包含我需要调用的静态工厂方法!),所有Linq表类(如Areas
或Towns
)实现公共接口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 :(得分:2)
你应该能够传递delegates / 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);
答案 1 :(得分: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>();
答案 2 :(得分: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);
}