Инъекция зависимостей с помощью Massive ORM: динамическая проблема - PullRequest
12 голосов
/ 23 июня 2011

Я начал работать над проектом MVC 3, который требует данных из огромной существующей базы данных.

Моя первая идея состояла в том, чтобы пойти дальше и использовать EF 4.1 и создать группу POCO для представлениятаблицы, которые мне нужны, но я начинаю думать, что отображение будет слишком сложным, поскольку мне нужны только некоторые столбцы в некоторых таблицах. (спасибо Стивену за разъяснения вкомментарии.

Так что я решил попробовать Massive ORM . Я обычно использую реализацию Unit of Work, поэтому я могу легко отделить все и использовать Dependency Injection. Это частьиз того, что у меня есть для 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 instead:

public override bool TryInvokeMember(InvokeMemberBinder binder, 
    object[] args, out object result) { }

Я не знаю, как "связать" эти методы в моем ISession.Как мой ISession может обеспечить поддержку First(), Last() и FindBy()?

Другими словами, как я могу использовать все возможностей Massive и при этом быть в состоянииотделить мои классы от доступа к данным?

Ответы [ 2 ]

8 голосов
/ 01 июля 2011

Я знаю, что на этот вопрос был дан ответ, но каждый метод в Massive помечен как виртуальный, так что вы можете легко его смоделировать.Я мог бы предложить это.ИЛИ - не беспокойтесь.

В настоящее время я делаю это для своего проекта для видеороликов MVC3 и беру страницу из книги пьес Rails - предлагая мои запросы в качестве статических методов для моих объектов и оттуда.Я позволил своим тестам поразить базу данных - она ​​совсем не тормозит и совершенно свободна, чтобы избавиться от всего оборудования.

В Rails нет DI / IoC, и это чувство счастья.

4 голосов
/ 24 июня 2011

Интерфейс

По сути, у вас есть пара опций интерфейса, подходящих для подписи для вашей сессии, Find, Last и FindBy.

Если вы хотите сохранить один и тот же синтаксис с именами динамических аргументов First, Last и Find должны быть геттерами и возвращать динамические с 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 , которая позволяет программно вызывать динамические методы, аналогично компилятору c # (, включая динамические именованные параметры ).

var arg = InvokeArg.Create;
return Impromptu.InvokeMember(table, "Find", arg("column", val),arg("otherColum", otherVal));

Или вы можете просто попытаться подделать параметры, поступающие в TryInvokeMember;

...