调用数据访问层的泛型方法

本文关键字:泛型方法 访问 数据 调用 | 更新日期: 2023-09-27 18:14:29

我正在创建一个具有三层架构的应用程序。

  • UI (web)
  • BLL (ClassLibrary)
  • 木豆(ClassLibrary)

我的需要是绑定下拉列表,如角色,城市,国家,州等

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

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

考虑下面的控制台应用程序示例,它复制了我的需求

假设这个调用来自我的UI

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;
}

这是我的数据访问层,我在这里使用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;
}

My Questions Are:

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

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

A和B是代码中的标签

调用数据访问层的泛型方法

你最好的选择是分支代码。然而,你可以通过在helper类中声明一些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>();
    //...
}

还是不明白你的第二个要求

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

如果你的业务层中有很多这样的泛型调用,你应该在你的DAL中公开泛型数据访问器(如果你使用EF,这是简单明了的)。

这意味着

  1. 您应该为这些项目建立一个公共接口,例如

    public interface IReferenceData
    {
        string Id { get; set; }
        string Name { get; set; }
    }
    
  2. 你应该公开通用方法来获取它

    public IEnumerable<T> GetReferenceData<T>() where T: IReferenceData
    

这样你的BLL就会像

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

(尽管在这种情况下不需要BLL)

Update:实际上,您不需要接口,我只是习惯这样做,以便我可以添加一些处理到BLL。这个问题不需要它

首先,您可以轻松地在应用程序中引入Repository模式。记住,Repository是域层(BLL)中的接口,在基础设施层(DAL)中实现。通用存储库通常有一个基类,它封装了所有实体和标识(键)类型的所有基本CRUD操作。

然后您可以使用依赖注入库(领域层中的存储库接口)将接口绑定到实现,或者甚至更好,创建应用层,它的契约(接口)将是您的用例,而实现将是粘合代码,它将域和基础结构代码绑定在一起以执行所述用例。阅读更多关于领域驱动设计的内容。

也就是说,有一种更现代的方式来与存储交互——实现命令&查询隔离。其中所有的数据读取都是查询,写入都是命令。它们都有一个通用的基础,封装了大量的逻辑。而不是存储库,它会被很多方法膨胀,你会得到很多单独的命令&(希望)更容易管理的查询类。

看一看提供的链接,这不是火箭科学,实际上,所有的部分都很容易适应一个大的图片随着时间的推移。

您可以使用反射来获取数据层类型并使用MethodInfo。调用通过字符串名称调用方法,使用所需返回类型的类型名称。我做了一个简短的例子,但由于我在手机上,所以无法进行测试!

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