系统设计时,往往要考虑到兼容多种数据库,拿常见的三种数据库:SqlServer,MySql,Oracle为例,常见的三层设计可以分为:业务逻辑层,数据访问层,实体层;他们的结构大致如下:
三种数据库对应有三套数据库访问类,为了方便组织代码,往往将读写一种数据库的类放到对应命名的文件夹下,代码结构大概如下:
业务逻辑层:
以上面的代码为例,业务逻辑层要调用数据访问层时,可以这样来实例化数据库访问对象:var db = DbFactory.GetService<IAdministrator>();
数据访问层:
关键点在于如何动态实例化数据库访问对象,即上面的DbFactory.GetService方法如何实现。
using System;
using System.Configuration;
using System.Reflection;
namespace Whir.Website.Admin.Repository
{
public class DbFactory
{
public static T GetService<T>()
{
string dbType = ConfigurationManager.AppSettings.Get("DbType");
Type interfaceType = typeof(T);
Assembly[] assemblies = AppDomain.CurrentDomain.GetAssemblies();
foreach (Assembly assembly in assemblies)
{
string asmName = assembly.FullName.Contains(",")
? assembly.FullName.Substring(0,
assembly.FullName.IndexOf(",",
StringComparison
.Ordinal))
: assembly.FullName;
if (assembly.FullName.ToLower().StartsWith("whir"))
{
//查找 接口所在程序集的类
if (interfaceType.Namespace != null
&&
(interfaceType.Namespace.Length >= asmName.Length && interfaceType.Namespace.Contains(asmName)))
{
Type[] classes = assembly.GetTypes();
foreach (Type type in classes)
{
//查找条件:
//1.实现了接口的类;
//2.类所在的命名空间含有配置文件配置的数据类型;
if (IsInherit(type, interfaceType)
&& (type.Namespace != null && type.Namespace.ToLower().Contains(dbType.ToLower())))
{
var temp = (T)Activator.CreateInstance(type);
return temp;
}
}
}
}
}
return default(T);
}
public static bool IsInherit(Type type, Type baseType)
{
if (type.BaseType == null) return false;
if (type.BaseType == baseType || baseType.IsAssignableFrom(type))
return true;
return IsInherit(type.BaseType, baseType);
}
}
}
以上代码即可实现:根据配置文件设置的数据库类型,动态实例化对应的数据库访问对象。