在泛型 class 中从给定类型 T 创建一个 IEnumerable<SelectListItem> 集合
Create an IEnumerable<SelectListItem> collection off a given type T in a generic class
我想添加一个方法,为我的项目中的实体创建一个 IEnumerable。所有实体都将呈现一个用于捕获/编辑的下拉列表,因此在我看来,将其添加到我的通用存储库方法中是有意义的。
我不太确定这是否可行,或者如何最好地解决这个问题,因为我使用的是通用的 classes,希望下面的代码能证明我的想法:
public interface ISpaceRepository<T>
where T : class
{
SpaceResult<T> GetAll();
SpaceResult<T> FindBy(Expression<Func<T, bool>> predicate);
SpaceResult<T> Add(T entity);
SpaceResult<T> Delete(T entity);
SpaceResult<T> Edit(T entity);
SpaceResult<T> FindById(int id);
SpaceResult<T> SelectList();
}
非常基本的接口定义。这在我的 SpaceRespository class:
中实现
public class SpaceRepository<T>
: ISpaceRepository<T> where T : class
{
// content omitted for ease of reading
}
在我的存储库中,我想为类型 T 创建一个方法来构建 IEnumerable 集合。这里的问题是,默认情况下,T 不公开任何属性,所以我不能得到 T.Name 和 T.Id,所以我正在使用谓词来完成工作:
public SpaceResult<T> SelectList(Expression<Func<T, bool>> predicate)
{
SpaceResult<T> result = new SpaceResult<T>();
try
{
result.SelectList = this.GetAll().Select(predicate);
}
catch (System.Exception ex)
{
result.IsError = true;
result.Message = ex.Message;
result.InnerException = ex.InnerException.Message;
}
return result;
}
这种方法有效,但每次我构建 select 项的集合以绑定到 Razor (MVC) 中的下拉列表时,我都必须定义谓词。
有没有更简单的方法?反思的代价太大了。没有特别的理由不在视图模型级别执行此操作,我只是在学习时尝试了几个想法 :$.
更新
这个想法是公开一个通用方法,该方法将在存储库模式中为 T 的给定数据库实体创建 SelectListItem 元素的集合,而无需我或其他开发人员为其中的每个表复制代码数据库。
更新 1
一个例子:
ISpaceRepository<Building> _repo = new SpaceRepository<Building>();
SpaceResult<Building> result = this._repo.SelectList((x => new SelectListItem {
x.Id,
x.Description }));
更新 2
建筑看起来像这样:
[Table("buildings")]
public class Building
{
[Column("id")]
[Key]
public int Id {get;set;}
[Column("description")]
public string Description {get;set;}
}
所以我在想,也许如果我在 select 列表中向我需要的列添加一个自定义属性,我就可以使用反射,但这对于我想要的解决方案来说听起来很昂贵.
[Table("buildings")]
public class Building
{
[Column("id")]
[Key]
[SelectListItem]
public int Id {get;set;}
[Column("description")]
[SelectListItem]
public string Description {get;set;}
}
怎么样:
interface IEntity {
public int Id { get; }
public string Name { get; }
}
[Table("buildings")]
public class Building : IEntity
{
[Column("id")]
[Key]
public int Id {get;set;}
[Column("description")]
public string Description {get;set;}
[NotMapped]
public string Name { get { return this.Description; } }
}
[Table("cars")]
public class Car : IEntity
{
[Column("id")]
[Key]
public int Id {get;set;}
[Column("title")]
public string Title {get;set;}
[NotMapped]
public string Name { get { return this.Title; } }
}
然后编写一个适用于实现此接口的元素的方法就足够了吗?
方法:
public SpaceResult<IEntity> SelectList()
{
SpaceResult<IEntity> result = new SpaceResult<IEntity>();
try
{
result.SelectList = this.GetAll().Select(x => new SelectListItem { x.Id, x.Name });
}
catch (System.Exception ex)
{
result.IsError = true;
result.Message = ex.Message;
result.InnerException = ex.InnerException.Message;
}
return result;
}
用法:
ISpaceRepository<Building> _repo = new SpaceRepository<Building>();
SpaceResult<IEntity> result = this._repo.SelectList();
或
ISpaceRepository<Car> _repo = new SpaceRepository<Car>();
SpaceResult<IEntity> result = this._repo.SelectList();
只要您的所有实体类实现了公共接口,就可以应用相同的方法。
我想添加一个方法,为我的项目中的实体创建一个 IEnumerable。所有实体都将呈现一个用于捕获/编辑的下拉列表,因此在我看来,将其添加到我的通用存储库方法中是有意义的。
我不太确定这是否可行,或者如何最好地解决这个问题,因为我使用的是通用的 classes,希望下面的代码能证明我的想法:
public interface ISpaceRepository<T>
where T : class
{
SpaceResult<T> GetAll();
SpaceResult<T> FindBy(Expression<Func<T, bool>> predicate);
SpaceResult<T> Add(T entity);
SpaceResult<T> Delete(T entity);
SpaceResult<T> Edit(T entity);
SpaceResult<T> FindById(int id);
SpaceResult<T> SelectList();
}
非常基本的接口定义。这在我的 SpaceRespository class:
中实现public class SpaceRepository<T>
: ISpaceRepository<T> where T : class
{
// content omitted for ease of reading
}
在我的存储库中,我想为类型 T 创建一个方法来构建 IEnumerable 集合。这里的问题是,默认情况下,T 不公开任何属性,所以我不能得到 T.Name 和 T.Id,所以我正在使用谓词来完成工作:
public SpaceResult<T> SelectList(Expression<Func<T, bool>> predicate)
{
SpaceResult<T> result = new SpaceResult<T>();
try
{
result.SelectList = this.GetAll().Select(predicate);
}
catch (System.Exception ex)
{
result.IsError = true;
result.Message = ex.Message;
result.InnerException = ex.InnerException.Message;
}
return result;
}
这种方法有效,但每次我构建 select 项的集合以绑定到 Razor (MVC) 中的下拉列表时,我都必须定义谓词。
有没有更简单的方法?反思的代价太大了。没有特别的理由不在视图模型级别执行此操作,我只是在学习时尝试了几个想法 :$.
更新
这个想法是公开一个通用方法,该方法将在存储库模式中为 T 的给定数据库实体创建 SelectListItem 元素的集合,而无需我或其他开发人员为其中的每个表复制代码数据库。
更新 1
一个例子:
ISpaceRepository<Building> _repo = new SpaceRepository<Building>();
SpaceResult<Building> result = this._repo.SelectList((x => new SelectListItem {
x.Id,
x.Description }));
更新 2
建筑看起来像这样:
[Table("buildings")]
public class Building
{
[Column("id")]
[Key]
public int Id {get;set;}
[Column("description")]
public string Description {get;set;}
}
所以我在想,也许如果我在 select 列表中向我需要的列添加一个自定义属性,我就可以使用反射,但这对于我想要的解决方案来说听起来很昂贵.
[Table("buildings")]
public class Building
{
[Column("id")]
[Key]
[SelectListItem]
public int Id {get;set;}
[Column("description")]
[SelectListItem]
public string Description {get;set;}
}
怎么样:
interface IEntity {
public int Id { get; }
public string Name { get; }
}
[Table("buildings")]
public class Building : IEntity
{
[Column("id")]
[Key]
public int Id {get;set;}
[Column("description")]
public string Description {get;set;}
[NotMapped]
public string Name { get { return this.Description; } }
}
[Table("cars")]
public class Car : IEntity
{
[Column("id")]
[Key]
public int Id {get;set;}
[Column("title")]
public string Title {get;set;}
[NotMapped]
public string Name { get { return this.Title; } }
}
然后编写一个适用于实现此接口的元素的方法就足够了吗?
方法:
public SpaceResult<IEntity> SelectList()
{
SpaceResult<IEntity> result = new SpaceResult<IEntity>();
try
{
result.SelectList = this.GetAll().Select(x => new SelectListItem { x.Id, x.Name });
}
catch (System.Exception ex)
{
result.IsError = true;
result.Message = ex.Message;
result.InnerException = ex.InnerException.Message;
}
return result;
}
用法:
ISpaceRepository<Building> _repo = new SpaceRepository<Building>();
SpaceResult<IEntity> result = this._repo.SelectList();
或
ISpaceRepository<Car> _repo = new SpaceRepository<Car>();
SpaceResult<IEntity> result = this._repo.SelectList();
只要您的所有实体类实现了公共接口,就可以应用相同的方法。