34

Jestem w trakcie tworzenia niestandardowego dostawcy członkostwa dla witryny ASP.Net MVC. Dostawca jest tworzony jako oddzielna klasa jako część większej biblioteki. Istnieje zapotrzebowanie na elastyczną bazę danych zaplecza, ponieważ może to być baza danych Xml lub baza danych SQL. Moją pierwszą myślą było stworzenie interfejsu dla magazynu danych i wstrzyknięcie go do dostawcy za pomocą wtrysku zależności.Wstrzyknięcia zależne i dostawcy członkostwa ASP.Net

Konieczne jest, aby programista mógł odziedziczyć interfejs bazy danych i udostępnić wymagane metody aktualizacji danych, które następnie zostaną wykorzystane przez dostawców członkostwa niestandardowego.

Jednak przez mój własny brak umiejętności nie mogę wymyślić, jak wprowadzić klasę do dostawcy członkostwa, dodając go do strony internetowej? Co należy zrobić, aby połączyć magazyn danych z dostawcą? Jaki byłby najprostszy sposób włączenia tego na stronie?

+0

Czy znasz jakieś struktury wtrysku zależności? – Restuta

+0

@Restuta - Nie. Nie szukam ram. Wystarczy prosty interfejs dla tego konkretnego wymagania.Programiści powinni mieć możliwość tworzenia własnych sklepów typu back-end, po prostu dziedzicząc interfejs. – BinaryMisfit

+1

Myślę, że framework może zaoszczędzić mnóstwo czasu. Zostanie on użyty do wstrzyknięcia konkretnej realizacji do Twojego niestandardowego dostawcy członkostwa, to zadanie jest najbardziej złożone, ponieważ nie możesz kontrolować inicjowania dostawcy. – Restuta

Odpowiedz

31

Jeśli konfigurujesz dostawców członkostwa niestandardowego poprzez element członkowski> < w pliku Web.config, to widzę problemy, które wystąpią w przypadku wtrysku zależności.

Dostawcy są konstruowani i zarządzani przez framework i nie ma możliwości przechwycenia tej konstrukcji w celu zapewnienia dodatkowego wtrysku zależności dla interfejsu IDataStore.

Jeśli moje założenie jest poprawne, to można zastąpić metodę Initialize() w niestandardowym dostawcy i wykonać tam iniekcję zależności. Możesz mieć niestandardowe ustawienie nazwy/wartości w konfiguracji dostawcy, które wskazuje na typ implementujący IDataStore, który jest przekazywany jako część słownika do metody Initialize().

Następnie należy uruchomić instancję typu magazynu danych i ustawić go na odpowiednim miejscu:

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() zostanie wywołana przez ramy po to tworzy instancję operatora, dzięki czemu jest idealne miejsce do wykonania dodatkowych prac konfiguracyjnych, takich jak to.

Do testowania scenariuszy wystarczy ustawić właściwość składnicy danych w samej instancji dostawcy, ponieważ będzie ona tworzona bezpośrednio w testach.

+1

Idealny. Kod, którego szukałem. Dziękuję Ci! – BinaryMisfit

+0

Istnieje poprawka wykonana w podobny sposób, jak w tym miejscu: http://bugsquash.blogspot.com.au/2010/11/windsor-managed-membershipproviders.html W zasadzie implementuje wzór dekoracyjny Decorator, aby opakować instancję utworzoną przez Pojemnik DI. –

+0

To już nie działa w .Net 4.6.2 – IronSean

2

Najprostszym sposobem wykonania wstrzyknięcia zależnego, które widziałem (a właściwie jedynym, którego używałem do tej pory ...) jest posiadanie konstruktora klasy zależnej jako interfejsu, który przyjmuje interfejs i przypisanie do prywatnego pola. Jeśli chcesz, możesz również dodać "domyślny" konstruktor, który łączy się z pierwszym z domyślną wartością.

uproszczony, to będzie wyglądać mniej więcej tak:

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()) { } 
} 

Koncepcja jest nazywany „Konstruktor łańcuchowym”, i jest tam wiele artykułów w internecie o tym, jak to zrobić. Uważam, że jest to bardzo wyjaśniający wzór DI.

+0

Dzięki. Używam DI dość często, więc jestem całkiem zadowolony z tej części. Mój problem dotyczy dostawcy członkostwa, który jest skonfigurowany w pliku web.config. Rozwiązanie Sama rozwiązuje ten problem. – BinaryMisfit

+0

@Sleeper: Mówi, że używa ASP.NET MVC, co oznacza, że ​​* jest możliwe *, aby rozwiązać klasę przez kontener. Sugeruję, że powinien. A tak przy okazji, nie musisz krzyczeć. –

20

Czy to nie lepiej? Używam go z MVC3 i ninject. Wystarczy dodać właściwość do niestandardowej klasy dostawcy członkostwa. Pamiętaj, aby dodać "using System.Web.Mvc;" na szczycie.

public IRepository Repository 
{ 
    get 
    { 
     return DependencyResolver.Current.GetService<IRepository>(); 
    } 
} 
+0

Prawdopodobnie. Nie patrzyłem na to od jakiegoś czasu, a wtedy zadawano sobie pytanie, że wciąż jest to MVC 1.0 – BinaryMisfit

+1

To działa dla mnie. Wadą jest to, że jest to wariant anty-wzorcowy "Service Locator", ale czasami trzeba dokonać kompromisów architektonicznych. (Zobacz http://stackoverflow.com/questions/22795459/is-servicelocator-anti-pattern.) Nie wiem, czy mają to naprawić w ASP.NET vNext, ale miejmy nadzieję. –

Powiązane problemy