GenericsMethod调用数据访问层

时间:2015-09-25 13:53:05

标签: c# asp.net entity-framework generics

我正在使用3层架构创建应用程序。

  • UI(网页)
  • BLL(ClassLibrary)
  • DAL(ClassLibrary)

我的需求是绑定下拉列表,如角色,城市,国家,国家......等等。

我为所有实体创建了属性(都具有相同的结构),比如

public class City
{
    public string Id { get; set; }
    public string Name { get; set; }
}

考虑以下复制我需要的控制台应用程序的示例

假设此来自我的用户界面

static void Main( string[] args )
{

    List<City> cities = GetDataList<City>();
    List<Role> roles = GetDataList<Role>();

}

这是我的商业逻辑(BLL)

public static  List<T> GetDataList<T>() where T:class ,new()
{
    List<T> list = new List<T>();
 (A)   List<T> data = ** I am not getting the way how to call different methods of data acess here?
    foreach (var temp in data.AsEnumerable())
    {
        var obj = new T();
  ( B)     foreach (var prop in obj.GetType().GetProperties())
        {
            var propertyInfo = obj.GetType().GetProperty(prop.Name);
            propertyInfo.SetValue(obj , Convert.ChangeType(temp. , propertyInfo.PropertyType) , null);
        }
        list.Add(obj);
    }

    return list;
}

这是我的DataAcess图层,我在这里使用EF

public static IList<City> FetchCityData()
{
    List<City> dict = new List<City>();           
    dict.Add(new City{Id="1",Name="hello"});
   dict.Add(new City{Id="2",Name="world"});
    return dict;
}

public static List<Role> FetchStateData()
{
    List<Role> dict = new List<Role>();
    dict.Add(new Role { Id = "1" , Name = "hello" });
    dict.Add(new Role { Id = "2" , Name = "world" });
    return dict;
}

我的问题是:

A)如何从BLL访问不同的Dataacess方法?

B)我如何在这里为我的类属性赋值?

A和B是代码中的标签。

4 个答案:

答案 0 :(得分:1)

正如我所说,你最好的选择是分支代码。但是你可以通过在辅助类中声明的一些Dictionary<Type, Func<object>>来使它更整洁:

public static class DataFetcher {
    static Dictionary<Type, Func<object>> _fetchers;
    static Dictionary<Type, Func<object>> Fetchers {
      get {
          if(_fetchers == null) _fetchers = new Dictionary<Type, Func<object>>();
          return _fetchers;
      }
    }
    static DataFetcher(){
       Fetchers[typeof(City)] = FetchCityData;
       Fetchers[typeof(State)] = FetchStateData;
    }
    public static IList<T> FetchData<T>(){
       Func<object> f;
       if(Fetchers.TryGetValue(typeof(T), out f)){
           return (IList<T>) f();
       }
       return null;
    }
}

<强>用法

public static  List<T> GetDataList<T>() where T:class ,new()
{
    var data = DataFetcher.FetchData<T>();
    //...
}

仍然不了解你的第二个要求。

答案 1 :(得分:1)

实际上,你的DAL设计是错误的。

如果您在业务层中有很多类似的通用调用,那么您应该在DAL中公开通用数据访问器(如果您使用的是EF,这很简单)。

这意味着

  1. 您应该为这些项目建立一个通用界面,例如

    public interface IReferenceData
    {
        string Id { get; set; }
        string Name { get; set; }
    }
    
  2. 您应该公开泛型方法来获取它

    public IEnumerable<T> GetReferenceData<T>() where T: IReferenceData
    
  3. 这样你的BLL就像

    一样简单
    public static List<T> GetDataList<T>() where T: IReferenceData
    {
        return Dal.GetReferenceData<T>().ToList()
    }
    

    (虽然在这种情况下你只是不需要BLL)

    更新:实际上,你不需要界面,我只是习惯这样做,所以我可以为BLL添加一些处理。这个问题不需要它。

答案 2 :(得分:1)

首先,您可以轻松地将Repository模式引入您的应用程序。请记住,Repository是域层(BLL)中的一个接口,在Infrastructure层实现(DAL去那里)。通用存储库通常具有基类,该基类封装了所有实体和标识(密钥)类型的所有基本CRUD操作。

然后你可以使用Dependency Injection库(Domain layer中的存储库接口)将接口绑定到实现,甚至更好,创建应用层,合同(接口)将是你的用例,实现将是the glue代码,它将域和基础结构代码联系起来以执行所述用例。详情请阅读Domain Driven Design

也就是说,有一种更现代的方式与存储 - 工具Command & Query segregation进行交互。所有数据读取均为queries且写入为commands。它们都将具有封装大量逻辑的通用基础。而不是存储库,可以通过很多方法膨胀,你会得到很多单独的命令&amp;查询类(希望)更容易管理。

看一下所提供的链接,实际上并不是那种火箭科学,而且随着时间的推移,所有部分都很容易适应大局。

答案 3 :(得分:0)

您可以使用反射来获取数据层类型,并使用MethodInfo.Invoke通过字符串名称调用方法,并使用所需返回类型的类型名称。我已经举了一个简单的例子,但我不能在我的手机上测试它!

Type dalType = Type.GetType("dalnamespace")

MethodInfo methodInfo = dalType.GetMethod(string.Format("Fetch{0}Data", objectTypeStringHere)); 
var returnValue = (List<T>)methodInfo.Invoke(dalType, null);