Konsultacje: wtorek, 1015 - 1145
punkty | ocena |
< 25 | ndst |
25-50 | dst |
50-75 | db |
> 75 | bdb |
Od kiedy | Do kiedy | Rozdziały |
---|---|---|
- | 13.04.2010 (włącznie) | 1.*, 2.* |
- | 11.05.2010 (włącznie) | 3.1, 3.2 |
- | 08.06.2010 (włącznie) | 3.3, 3.4, 3.5, 3.6 |
- | do końca semestru | pozostałe |
2010-03-09
class SmtpFacade { public void Send( string From, string To, string Subject, string Body, Stream Attachment, string AttachmentMimeType ); }
public class Person { } public class PersonDataContext { private Messenger _messenger = new Messenger(); private ListZrefaktoryzować ten przykład do wzorca Bridge tak, aby możliwe było wykorzystanie jednej z dwóch implementacji specjalizowanych klasy PersonDataContext, z których jedna XmlPersonDataContext wczyta dane listy osobowej z pliku XML, a druga TextFilePersonDataContext wczyta dane listy osobowej z pliku tekstowego i złożenie wybranej implementacji PersonDataContext z jedną z dwóch implementacji specjalizowanych klasy Messenger: FileMessenger, która utworzy plik o nazwie takiej jak identyfikator użytkownika z wiadomością w środku i HttpPostMessenger, która użyje WebRequest do nawiązania połączenia ze stroną domową użytkownika._persons; public void LoadPersons() { _persons = ...; } public void NotifyPersons() { foreach ( Person person in _persons ) _messenger.Nofify( person ); } } public class Messenger() { public void Notify( Person person ) { } }
public class ResourceManager { public Bitmap CachedBitmap( string Name ) { } }która utworzy nowy obiekt Bitmap z pliku o podanej nazwie i zapamięta go dla kolejnych wywołań. Do przechowywania stanu obiektów dla Flyweight najczęściej używa się kolekcji asocjacyjnych.
Chciałbym żeby w trakcie ćwiczeń powstały co najmniej dwie implementacje, w dwóch zespołach, a następnie żebyśmy mogli wymienić się implementacjami, obejrzeć je, porównać i nawzajem skomentować.
public class SimpleContainer { public void RegisterType<T>( bool Singleton ) where T : class; public void RegisterType<From, To>( bool Singleton ) where To : From; public T Resolve<T>(); }Podstawową metodą dla klienta kontenera jest metoda Resolve, której klient używa do tworzenia instancji obiektów:
SimpleContainer c = new SimpleContainer(); Foo fs = c.Resolve<Foo>();
SimpleContainer c = new SimpleContainer(); c.RegisterType<Foo>( true ); Foo f1 = c.Resolve<Foo>(); Foo f2 = c.Resolve<Foo>(); // f1 == f2Drugie przeciążenie służy do wyboru pożądanej implementacji klasy bazowej, abstrakcyjnej lub interfejsu:
SimpleContainer c = new SimpleContainer(); c.RegisterType<IFoo, Foo>( false ); IFoo f = c.Resolve<IFoo>(); // f ma typ Foo c.RegisterType<IFoo, Bar>( false ); IFoo g = c.Resolve<IFoo>(); // g ma typ BarUwaga. Nasza polityka zarządzania czasem życia obiektów przewiduje wyłącznie możliwość tworzenia obiektów ulotnych (w terminologii IoC mówi się transient) lub singetonów. W rzeczywistości bywa tak, że oprócz wbudowanych tych dwóch typowych polityk, może być zaimplementowana dowolna dodatkowa, np. w Unity jest tak. Uwaga. Jeżeli kontener nie ma zarejestrowanego typu interfejsu, a klient żąda obiektu typu interfejsu, powinien dowiedzieć się o tym jakimś rozsądnym wyjątkiem:
SimpleContainer c = new SimpleContainer(); IFoo f = c.Resolve<IFoo>(); // jakiś rozsądny wyjątek
public class SimpleContainer { ... public void RegisterInstance<T>( T Instance ); } SimpleContainer c = new SimpleContainer; IFoo foo1 = new Foo(); c.RegisterInstance<IFoo>( foo ); IFoo foo2 = c.Resolve<IFoo>(); // foo1 == foo2
class A { public A( B b ) { } } class B { } SimpleContainer c = new SimpleContainer(); A a = c.Resolve<A>(); // kontener wykonstruuje A z wstrzykniętą instancją B class X { public X( Y d, string s ) { }; } class Y { } SimpleContainer c = new SimpleContainer(); X x = c.Resolve<X>(); // wyjątek, string nie ma konstruktora bezparametrowego i nie da się rozwikłać żadnego z konstruktorów // ... ale .... c.RegisterInstance( "ala ma kota" ); // rejestruje instancję string, w C# parametr generyczny można opuścić w wywołaniu generycznym X x = c.Resolve<X>(); // jest ok, zarejestrowano instancję string więc rozwikłanie konstruktora X jest możliwe
public class A { public A( B b ) { } [Dependency] public C TheC { get; set; } } public class B { } public class C { } SimpleContainer c = new SimpleContainer(); A a = c.Resolve<A>(); // tworzy nową instancję A z B wstrzykniętym przez konstruktor i C wstrzykniętym przez właściwość
public class SimpleContainer { ... public void BuildUp<T>( T Instance ); } SimpleContainer c = new SimpleContainer(); A theA = ....; // obiekt theA SKĄDŚ pochodzi, ale nie z kontenera c.BuildUp( theA ); // wstrzykuje do theA zależności przez właściwości, tu: TheC
public delegate SimpleContainer ContainerProviderDelegate(); public class ServiceLocator { public static void SetContainerProvider( ContainerProviderDelegate ContainerProvider ) { ... } public static ServiceLocator Current { get { ... singleton ... } } public T GetInstance<T>(); } // Przykład 1, rejestrowanie lokatora SimpleContainer c = new SimpleContainer(); ContainerProviderDelegate containerProvider = () => c; ServiceLocator.SetContainerProvider( containerProvider ); /* zapamiętano funkcję rozwikłującą referencję do kontenera - to zawsze będzie TEN sam kontener */ // Przykład 2, rejestrowanie lokatora ContainerProviderDelegate containerProvider = () => new SimpleContainer(); ServiceLocator.SetContainerProvider( containerProvider ); /* zapamiętano funkcję rozwikłującą referencję do kontenera - to zawsze będzie NOWY kontener */ // Przykład 3, kod kliencki class Foo void Bar() { IService service = ServiceLocator.Current.GetInstance<IService>(); // GetInstance używa zarejestrowanej metody do rozwikływania kontenera do pobrania kontenera i rozwikłania zależności // Tym razem jednak IService nie musiało być wstrzykiwane } }
SimpleContainer c = new SimpleContainer(); c .RegisterType<Foo>( true ) .RegisterType<IBar, Baz>( false ) .RegisterInstance<IQux>( qux );
<?xml version="1.0"?> <configuration> <configSections> <section name="simpleIoCContainer" type="Uwr.SimpleIoC.SimpleContainerConfigurationSection" /> ... </configSections> ... <simpleIoCContainer> <resolvableTypes> <add type="Foo" singleton="true" /> <add type="IBar" mapsTo="Baz" /> /* brak atrybutu singleton oznacza singleton=false */ </resolvableTypes> </simpleIoCContainer>
SimpleContainer c = new SimpleContainer(); SimpleContainerConfigurationSection iocConfig = (SimpleContainerConfigurationSection)ConfigurationManager.GetSection( "simpleIoCContainer" ); iocConfig.Configure( c );
int Abs( int n ) { }
int Min( int[] tab ) { }