Внедрение зависимостей и поставщики членства в ASP.Net

Я занимаюсь созданием настраиваемого поставщика членства для веб-сайта ASP.Net MVC. Провайдер создается как отдельный класс как часть более крупной библиотеки. Необходимо, чтобы внутреннее хранилище данных было гибким, так как это может быть XML-файл или база данных SQL. Моя первоначальная мысль заключалась в том, чтобы создать интерфейс для хранилища данных и внедрить его в провайдер с помощью внедрения зависимостей.

Конечным результатом является то, что разработчик может унаследовать интерфейс хранилища данных и предоставить необходимые методы для обновления данных, которые затем будут использоваться настраиваемыми поставщиками членства.

Однако из-за отсутствия навыков я не могу понять, как ввести класс в поставщика членства при добавлении его на веб-сайт? Что нужно сделать, чтобы связать хранилище данных с провайдером? Каким будет самый простой способ включить это на веб-сайте?


person BinaryMisfit    schedule 11.10.2009    source источник
comment
Вы знакомы с какими-либо фреймворками для внедрения зависимостей?   -  person Restuta    schedule 11.10.2009
comment
@Restuta - Нет. Я не ищу фреймворк. Для этого конкретного требования будет достаточно простого интерфейса. Разработчики должны иметь возможность создавать свои собственные внутренние хранилища, просто наследуя интерфейс.   -  person BinaryMisfit    schedule 11.10.2009
comment
Я думаю, что фреймворк может сэкономить вам много времени. Он будет использоваться для внедрения конкретной реализации в ваш настраиваемый поставщик членства, эта задача наиболее сложна, поскольку вы не можете контролировать инициализацию поставщика.   -  person Restuta    schedule 11.10.2009
comment
@Restuta - Справедливый комментарий, но это не то, что я ищу. Первый приз - это сделать это с использованием метода, который я имел в виду выше. Я предпочитаю не зависеть от внешних фреймворков, которые предоставляют больше, чем мне нужно.   -  person BinaryMisfit    schedule 11.10.2009


Ответы (3)


Если вы настраиваете настраиваемых поставщиков членства с помощью элемента ‹membership> в файле Web.config, я могу видеть проблемы, которые могут возникнуть при внедрении зависимостей.

Поставщики конструируются и управляются фреймворком, и у вас нет возможности перехватить эту конструкцию, чтобы обеспечить дополнительную инъекцию зависимостей для интерфейса IDataStore.

Если мое предположение верно, то вы можете переопределить метод Initialize() в вашем настраиваемом провайдере и выполнить там внедрение зависимостей. Вы можете иметь настраиваемую настройку имени / значения в конфигурации поставщика, которая указывает на тип, реализующий IDataStore, который передается как часть словаря методу Initialize().

Затем вы активируете экземпляр типа хранилища данных и устанавливаете его в соответствующем свойстве:

public class MyMembershipProvider : MembershipProvider
{
    public IDataStore DataStore
    {
        get;
        set;
    }

    public override Initialize(string name, NameValueCollection config)
    {
        var dataStoreType = config["dataStoreProvider"];
        if (!String.IsNullOrEmpty(dataStoreType))
        {
            var type = Type.GetType(dataStoreType);
            DataStore = (IDataStore) Activator.CreateInstance(type);
        }
    }
}

Initialize() будет вызываться фреймворком после создания экземпляра вашего провайдера, так что это идеальное место для выполнения любой дополнительной работы по настройке, такой как эта.

Для сценариев тестирования вы просто устанавливаете свойство хранилища данных в самом экземпляре поставщика, так как вы будете создавать его непосредственно в своих тестах.

person Sam    schedule 12.10.2009
comment
Исправление, выполненное аналогичным образом, можно найти здесь: bugsquash. blogspot.com.au/2010/11/ Он в основном реализует шаблон проектирования Decorator, чтобы обернуть экземпляр, созданный вашим контейнером DI. - person Mark Whitfeld; 10.01.2014

Разве так не лучше? Я использую его с MVC3 и ninject. Достаточно добавить свойство в свой собственный класс поставщика членства. Не забудьте добавить "using System.Web.Mvc;" наверху.

public IRepository Repository
{
    get
    {
        return DependencyResolver.Current.GetService<IRepository>();
    }
}
person Michal B.    schedule 04.12.2011
comment
Возможно. Я давно не смотрел на это, и в то время, когда был задан вопрос, это все еще был MVC 1.0. - person BinaryMisfit; 04.12.2011
comment
Меня устраивает. Обратной стороной является то, что это разновидность анти-шаблона Service Locator, но иногда приходится идти на архитектурные компромиссы. (См. stackoverflow.com/questions/22795459/ ) Я не знаю, должны ли они исправить это в ASP.NET vNext, но, надеюсь. - person Ken Smith; 16.03.2015

Самый простой способ сделать инъекцию зависимостей, который я видел (и на самом деле единственный, который я использовал до сих пор ...), - это заставить конструктор вашего зависимого класса принять интерфейс в качестве параметра и назначить его частному поле. Если хотите, вы также можете добавить конструктор «по умолчанию», который будет цепляться за первый конструктор со значением по умолчанию.

В упрощенном виде это будет выглядеть примерно так:

public class DependentClass
{
    private IDataStore _store;

    // Use this constructor when you want strict control of the implementation
    public DependentClass(IDataStore store)
    {
         this._store = store;
    }

    // Use this constructor when you don't want to create an IDataStore instance
    // manually every time you create a DependentClass instance
    public DependentClass() : this(new DefaultDataStore()) { }
}

Эта концепция называется «цепочка конструкторов», и в Интернете есть много статей о том, как это сделать. Я считаю, что этот учебник очень хорошо объясняет шаблон DI.

person Tomas Aschan    schedule 11.10.2009
comment
Спасибо. Я довольно часто использую DI, поэтому мне эта часть вполне комфортна. Моя проблема связана с поставщиком членства, который настраивается в файле web.config. Решение Сэма решает эту проблему. - person BinaryMisfit; 12.10.2009
comment
@Sleeper: Он говорит, что использует ASP.NET MVC, а это означает, что возможно разрешить класс через контейнер. Я предлагаю ему это сделать. И, кстати, не надо кричать. - person Tomas Aschan; 09.03.2011