我正在使用3层架构创建应用程序。
我的需求是绑定下拉列表,如角色,城市,国家,国家......等等。
我为所有实体创建了属性(都具有相同的结构),比如
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是代码中的标签。
答案 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,这很简单)。
这意味着
您应该为这些项目建立一个通用界面,例如
public interface IReferenceData
{
string Id { get; set; }
string Name { get; set; }
}
您应该公开泛型方法来获取它
public IEnumerable<T> GetReferenceData<T>() where T: IReferenceData
这样你的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);