在泛型类</selectlistitem>中创建给定类型T的IEnumerable <selectlistitem>集合

时间:2015-04-02 11:47:39

标签: c# generics selectlistitem

我想添加一个方法,该方法将为我的项目中的实体创建IEnumerable。所有实体都会有一个下拉式渲染用于捕获/编辑,所以在我看来,将它添加到我的通用存储库方法是有意义的。

我不太确定这是否可行,或者如何最好地解决这个问题,因为我使用的是通用类,希望以下代码能够推销我的想法:

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类中实现:

public class SpaceRepository<T>
    : ISpaceRepository<T> where T : class
{
    // content omitted for ease of reading
}

在我的存储库中,我想为类型T创建一个将构建IEnumerable集合的方法。这里的问题是,默认情况下,T不暴露任何属性,所以我可以&#39 ;得到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;
    }

这种方法有效,但每次我构建一系列选择项以绑定到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;}
}

所以我想,如果我在选择列表中为我需要的列添加自定义属性,我可以使用反射,但这对于我之后的解决方案来说听起来很昂贵。 / p>

[Table("buildings")]
public class Building
{
    [Column("id")]
    [Key]
    [SelectListItem]
    public int Id {get;set;}

    [Column("description")]
    [SelectListItem]
    public string Description {get;set;}
}

1 个答案:

答案 0 :(得分:1)

怎么样:

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();

只要所有实体类都实现了公共接口,就可以应用相同的方法。