2010-12-14 12 views
21

W question o przydatności IoC kontenera, wygrywając submitter wspomnieć, że z kontenera IoC można zrobić tak:Kod Cruft. IoC na ratunek

public class UglyCustomer : INotifyPropertyChanged 
{ 
    private string _firstName; 
    public string FirstName 
    { 
     get { return _firstName; } 
     set 
     { 
      string oldValue = _firstName; 
      _firstName = value; 
      if(oldValue != value) 
       OnPropertyChanged("FirstName"); 
     } 
    } 

    private string _lastName; 
    public string LastName 
    { 
     get { return _lastName; } 
     set 
     { 
      string oldValue = value; 
      _lastName = value; 
      if(oldValue != value) 
       OnPropertyChanged("LastName"); 
     } 
    } 
} 

do tego:

var bindingFriendlyInstance = IoC.Resolve<Customer>(new NotifyPropertyChangedWrapper()); 

Pytania:

  • Który magiczny kontener IoC zapewnia tę dobroć?
  • Przykład implementujący to?
  • Jakieś wady?
  • W projekcie ze złożonymi zależnościami, czy będę płakać, gdy spróbuję zastosować powiązanie danych z tymi obiektami?
+1

Jestem prawie pewna, że ​​odpowiedź to tylko drażnienie się z "pomysłem", a nie rzeczywistą implementacją. –

+1

@chibacity. W takim przypadku Ben Scheirman jest lepszą złośliwością niż jakakolwiek dziwka, jaką kiedykolwiek widziałem. (W filmie, oczywiście). – AngryHacker

+0

, jeśli potrzebowałeś Klienta bez logiki, ale czystego DTO i powiadomień o zmianie właściwości, lepiej byłoby zadeklarować go jako interfejs, ICustomer, i to nie jest duża sprawa, aby stworzyć konkretną klasę z dynamicznym generowaniem kodu. –

Odpowiedz

9

Na Twój drugi fragment kodu do pracy, NotifyPropertyChangedWrapper pewno trzeba używać odbicie (lub dynamic), aby wygenerować klasę, która udostępnia interfejs kompatybilny z Customer i implementuje automatyczne powiadomienie nieruchomości. Nie powinno być żadnych problemów wiążących dane, ale byłoby trochę narzut.

uprościć wdrażanie, który wykorzystuje dynamiczne obiekt może wyglądać mniej więcej tak:

public class NotifyPropertyChangedWrapper<T> 
    : DynamicObject, INotifyPropertyChanged 
{ 
    private T _obj; 

    public NotifyPropertyChangedWrapper(T obj) 
    { 
     _obj = obj; 
    } 

    public override bool TryGetMember(
     GetMemberBinder binder, out object result) 
    { 
     result = typeof(T).GetProperty(binder.Name).GetValue(_obj); 
     return true; 
    } 

    // If you try to set a value of a property that is 
    // not defined in the class, this method is called. 
    public override bool TrySetMember(
     SetMemberBinder binder, object value) 
    { 
     typeof(T).GetProperty(binder.Name).SetValue(_obj, value); 
     OnPropertyChanged(binder.Name); 
     return true; 
    } 

    // Implement OnPropertyChanged... 
} 

Oczywiście, każdy kod, który pobiera jeden z tych obiektów stracą ładunki typu bezpieczeństwa. Inną opcją jest wygenerowanie klasy implementującej ten sam interfejs co zawijana klasa. Istnieje wiele przykładów na to w Internecie. Głównym wymogiem jest, aby Twój Customer musiał być albo interface, albo musiałby wszystkie jego właściwości były wirtualne.

+0

tak, jeśli potrzebowałeś Klienta bez logiki, ale czystego powiadomienia o zmianach DTO i zmianach roperty, lepiej byłoby ogłosić go jako interfejs, ICustomer, a wtedy taka konstrukcja nie jest aż tak duża, by stworzyć konkretną klasę z dynamiczne generowanie kodu. –

+0

W każdym razie, aby to zrobić bez DynamicObject? Jestem na .NET 3.5. I nie rezygnując z Intellisense. – AngryHacker

+0

Musisz zrobić to, co powiedział Pauli. Zrobiłem to już wcześniej, ale kod jest długi i nie mam go do dyspozycji. Oto artykuł, w którym robi to ktoś inny: http://grahammurray.wordpress.com/2010/04/13/dynamically-generating-types-to-implement-inififting_file/ – Jacob

2

Nigdy go nie używałem, ale można podobno stworzyć coś takiego za pomocą PostSharp.

3

Aby zrobić to w sposób ogólny (tj. Pojedynczy fragment kodu implementujący INotifyPropertyChanged dla dowolnej klasy) użyj serwera proxy. Istnieje wiele implementacji, aby to zrobić z Castle.DynamicProxy lub LinFu lub Unity. Te biblioteki proxy mają dobre wsparcie w kontenerach IoC, na przykład DynamicProxy ma dobrą integrację z Castle Windsor i przechwytywanie Unity (lub jakkolwiek się nazywa) ma oczywiście dobrą integrację z kontenerem Unity.

1

Jeśli szukasz konkretnego rozwiązania do automatycznego generowania obiektów wiążących, powinieneś spojrzeć na PropertyChanged.Fody (wcześniej NotifyPropertyWeaver). To przepisuje klasy implementujące INotifyPropertyChanged w celu uwzględnienia kodu powiadomienia. Istnieje przykład na stronie github.

Moim zdaniem jest to więcej niż przy użyciu proponowanego rozwiązania kontenera IOC. Jednak jest to biblioteka specyficzna dla wiązania INotifyPropertyChanged, więc nie ma zastosowania jako rozwiązanie ogólne, co zostało omówione w połączonym pytaniu.

+0

Pytanie dotyczyło konkretnie tego, który kontener *** IOC *** dostarczył tę funkcję. Nie otwieraj dwuletniego pytania ***, które ma zaakceptowaną odpowiedź ** z odpowiedzią, która tak naprawdę nie odpowiada na pytanie. – jgauffin

+0

Zinterpretowałem, że to pytanie wiąże się z redukcją kodu cruft, odpowiadałem z tej perspektywy. Myślę, że koncentruje się IOC głównie dlatego, że zainspirowała go inna kwestia MKOl. Nawet jeśli moja odpowiedź nie używa MKOl, uważam, że warto wskazać, że inne techniki mogą lepiej nadawać się do osiągnięcia pożądanego rezultatu. Również [to pytanie na temat meta] (http://meta.stackexchange.com/questions/20524/reviving-old-questions) stwierdza, że ​​odpowiadanie na stare pytania jest w porządku. –