[Wymagania: .NET 3.5]
Załóżmy że mamy zrealizować bardzo proste zadanie: zmienić wszystkim osobom o jakimś wieku ich imię. Więc...
Mapujemy osobę:
|
class Osoba { public int Id { get; set; } public string Imie { get; set; } public int Wiek { get; set; }
public override string ToString() { return string.Format("{0} {1} {2}", Id, Imie, Wiek); } }
Symulujemy działanie Data Access Layer (zwracającego wszystkie osoby)
interface IDal { IEnumerable<Osoba> Osoby { get; } }
class Dal : IDal { private IEnumerable<Osoba> osoby = new List<Osoba>() { new Osoba() { Id = 1, Imie = "osoba1", Wiek = 23}, new Osoba() { Id = 2, Imie = "osoba2", Wiek = 23}, new Osoba() { Id = 3, Imie = "osoba3", Wiek = 32} };
public IEnumerable<Osoba> Osoby { get { return osoby; } } }
Tworzymy Data Access Object (LINQ wyciągający osoby przy użyciu IDal) interface IDaoOsoby { IEnumerable<Osoba> FindByWiek(int wiek); }
class DaoOsoby : IDaoOsoby { private IDal dal;
public DaoOsoby(IDal dal) { this.dal = dal; }
public IEnumerable<Osoba> FindByWiek(int wiek) { return from osoba in dal.Osoby where osoba.Wiek == wiek select new Osoba() { Id = osoba.Id, Imie = osoba.Imie, Wiek = osoba.Wiek }; } }
Serwis odpowiedzialny za zmianie imion (główna logika) interface IServiceOsoby { void ZmienImie(int wiek); }
class ServiceOsoby : IServiceOsoby { private IDaoOsoby daoOsoby;
public ServiceOsoby(IDaoOsoby daoOsoby) { this.daoOsoby = daoOsoby; }
public void ZmienImie(int wiek) { IEnumerable<Osoba> osoby = daoOsoby.FindByWiek(wiek);
foreach (var osoba in osoby) { osoba.Imie = "zmienione imie"; } } }
Dzięki temu, że wszystko oparte zostało na interface'ach uzyskaliśmy bardzo elastyczną i niepowiązaną żadnymi zależnościami strukturę. Świetnie, o to właśnie nam chodziło :) Teraz wystarczy określić zachowanie przez "wstrzykniecie" konkretnych klas do konstruktorów. Jeśli chodzi o testy jednostkowe, to stworzenie ich nie będzie żadnym problemem. Dzięki użyciu Dependency Injection możemy testować jedną warstwę niezależnie od drugiej. Tutaj przyjdą nam z pomocą Mock'i, lecz zostawmy sobie to na później :)
Rzućmy okiem w jaki sposób możemy się tym wszystkim posługiwać.
class Program { static void Main(string[] args) { IDal dal = new Dal(); IDaoOsoby daoOsoby = new DaoOsoby(dal); IServiceOsoby service = new ServiceOsoby(daoOsoby);
service.ZmienImie(23);
ContainerBuilder cb = new ContainerBuilder();
cb.Register<Dal>().As<IDal>().SingletonScoped(); cb.Register(v => new DaoOsoby(v.Resolve<IDal>())).As<IDaoOsoby>(); cb.Register(v => new ServiceOsoby(v.Resolve<IDaoOsoby>())).As<IServiceOsoby>();
Container container = new Container(); cb.Build(container);
container.Resolve<IServiceOsoby>().ZmienImie(23); } }
|
|
Jest to tylko bardzo "drobny i ogólny" przedsmak tego co będzie działo w kolejnych postach :)
kod źródłowy
2 komentarze:
odnośnie wzorców projektowych to znalazłem zestaw fajnych przykladow i mysle ze warto opublikowac tego lina na Twoim blogu http://www.go4expert.com/forums/showthread.php?t=5127
no nie wygląda to za ciekawie:
cb.Register(v => new ServiceOsoby(v.Resolve())).As();
Prześlij komentarz