Я поиграл с некоторыми новыми шаблонами для n-слойного доступа к данным, и наткнулся на один, который кажется очень гибким и простым в реализации. По сути, мне нужно было решение, которое могло бы сделать различные уровни данных подключаемыми / swapabale на лету, то есть базовый доступ к данным из БД, распределенное кэширование, локальное кэширование и т. Д.
Приведенный ниже код легко повторно используется и невероятно эффективен - всего на несколько тактов дольше, чем мое предыдущее полностью жестко закодированное решение.
Как это выглядит? Есть ли способ, чтобы это могло быть реализовано лучше? Есть общие мысли или критика? Любой вклад от тех, кто использовал подобные шаблоны?
Базовый класс:
public class DataAdapterFactory<T> where T : class
{
private DataAdapter<T> Adapter;
public DataAdapterFactory(DataAdapterBase<T> Base)
{
Adapter = Base;
}
public void Extend<U>() where U : DataAdapterExtender<T>, T, new()
{
DataAdapterExtender<T> Extender = new U();
Extender.BaseAdapter = Adapter as T;
Adapter = Extender;
}
public T GetAdapter()
{
return Adapter as T;
}
}
public class DataAdapter<T> where T : class { }
public class DataAdapterBase<T> : DataAdapter<T> where T : class { }
public class DataAdapterExtender<T> : DataAdapter<T> where T : class
{
public T BaseAdapter;
}
Внедрение в DAL:
// base interface defines methods
public interface IMyDataAdapter
{
string GetString();
}
// base sql adapter
public class SqlDataAdapter : DataAdapterBase<IMyDataAdapter>, IMyDataAdapter
{
public string GetString()
{
return "SQL";
}
}
// provides cache support
public class DistributedCacheExtender : DataAdapterExtender<IMyDataAdapter>, IMyDataAdapter
{
public string GetString()
{
return BaseAdapter.GetString() + ", Distributed Cache";
}
}
// provides local cache support
public class LocalCacheExtender : DataAdapterExtender<IMyDataAdapter>, IMyDataAdapter
{
public string GetString()
{
return BaseAdapter.GetString() + ", Local Cache";
}
}
Доступ к данным:
public IMyDataAdapter GetAdapter()
{
// create adapter based on SqlDataAdapter
DataAdapterFactory<IMyDataAdapter> factory = new DataAdapterFactory<IMyDataAdapter>(new SqlDataAdapter());
// implement distributed cache
factory.Extend<DistributedCacheExtender>();
// implement local cache
factory.Extend<LocalCacheExtender>();
return factory.GetAdapter();
}
Используя указанную выше фабрику, любую комбинацию базовых адаптеров и удлинителей (Extend <> () необходимо вызывать в порядке выполнения) можно легко и без проблем использовать на лету через интерфейс, при этом бизнес-уровень ничего не знает о реализация.
В этом случае выше, вызов GetString () приведет к «SQL, распределенный кэш, локальный кэш». В реальном сценарии локальный кэш будет вызван первым. Если элемента там нет, мы бы отправились в распределенный кеш, а если его там нет, мы бы получили его из БД - и любой модуль мог бы быть заменен или вставлен по мере необходимости, в зависимости от объекта. , пользователь и т. д.