Dependecy Injection с массивным ORM: динамические проблемы
Я начал работать над проектом MVC 3, которому нужны данные из огромной существующей базы данных.
Моя первая идея заключалась в том, чтобы продолжить использование EF 4.1 и создать группу POCO для представления таблиц, которые мне нужны, но я начинаю думать, что сопоставление будет чрезмерно сложным, поскольку мне нужно только некоторые из столбцы в некоторых таблицах. (спасибо Steven для пояснения комментариев.
Так что я думал, что дам Massive ORM попробовать. Обычно я использую реализацию Unit of Work, поэтому я могу сохранить все красиво развязанными и использовать Injection Dependency. Это часть того, что у меня есть для Massive:
public interface ISession
{
DynamicModel CreateTable<T>() where T : DynamicModel, new();
dynamic Single<T>(string where, params object[] args)
where T : DynamicModel, new();
dynamic Single<T>(object key, string columns = "*")
where T : DynamicModel, new();
// Some more methods supported by Massive here
}
И здесь моя реализация интерфейса выше:
public class MassiveSession : ISession
{
public DynamicModel CreateTable<T>() where T : DynamicModel, new()
{
return new T();
}
public dynamic Single<T>(string where, params object[] args)
where T: DynamicModel, new()
{
var table = CreateTable<T>();
return table.Single(where, args);
}
public dynamic Single<T>(object key, string columns = "*")
where T: DynamicModel, new()
{
var table = CreateTable<T>();
return table.Single(key, columns);
}
}
Проблема связана с методами First()
, Last()
и FindBy()
. Massive основан на объекте dynamic
с именем DynamicModel
и не определяет какой-либо из вышеперечисленных методов; он обрабатывает их через реализацию TryInvokeMethod()
, превышающую DynamicObject
:
public override bool TryInvokeMember(InvokeMemberBinder binder,
object[] args, out object result) { }
Я не могу понять, как "взаимодействовать" с этими методами в моем ISession
. Как моя ISession
обеспечит поддержку First()
, Last()
и FindBy()
?
По-другому, как я могу использовать все возможности Massive и все еще иметь возможность отделить мои классы от доступа к данным?
Ответы
Ответ 1
Интерфейс
В принципе, у вас есть несколько вариантов интерфейса, подходящих для подписи для вашего ISession Find, Last и FindBy.
Если вы хотите сохранить один и тот же синтаксис с именами динамических аргументов First, Last и Find, все должны быть getters и возвращать динамические с помощью DynamicObject, который реализует bool TryInvoke(InvokeBinder binder, object[] args, out object result)
, который даст вам тот же синтаксис dynamic Find(column:val, otherColum:otherVal)
. Вот приблизительный пример:
public class MassiveSession : ISession
{
...
public dynamic Find{
get {
return new DynamicInvoker(this,name:"Find");
}
}
public class DynamicInvoker : DynamicObject{
...
public override bool TryInvoke(InvokeBinder binder, object[] args, out object result)
{
...
return true;
}
}
}
Если вам нужны полностью статически определенные методы, вам просто нужно будет сделать один параметр IDictionary или что-то, чтобы дать вам пары ключей.
Пересылка вызова динамическому методу Massive
Есть два способа сделать это.
Простым способом является использование фреймворка с открытым исходным кодом ImpromptuInterface, который позволяет программным способом вызывать динамические методы, подобно компилятору С# (включая динамические именованные параметры).
var arg = InvokeArg.Create;
return Impromptu.InvokeMember(table, "Find", arg("column", val),arg("otherColum", otherVal));
Или вы можете просто попытаться подделать параметры, входящие в TryInvokeMember
;
Ответ 2
Я знаю, что на этот вопрос был дан ответ - но каждый метод в Massive отмечен как виртуальный, чтобы вы могли легко его пробить. Я мог бы предположить это. ИЛИ - не беспокойтесь.
Я делаю это в своем проекте в настоящее время для видео MVC3 и беру страницу из рецензии Rails - предлагаю свои запросы как статические методы на своих объектах и оттуда. Я позволил своим испытаниям попасть в базу данных - это совсем не замедляет работу и освобождает все механизмы.
Там нет DI/IoC в Rails, и это счастливое чувство.