2013-06-10 11 views
7

Widziałem podobne pytania/odpowiedzi dla tego zamieszczonego w przeszłości, ale moje różni się nieco od innych, które widziałem.Dynamiczny wybór metody opartej na parametrze wykonawczym typ

Zasadniczo mam wspólny interfejs i kilka klas, które implementują/dziedziczą z niego. Następnie, w osobnej klasie, mam metody, które muszą działać na obiektach podanych przez interfejs IObject. Jednak każdy z nich musi być realizowany na różne sposoby, dlatego istnieje osobna deklaracja metody dla każdego konkretnego typu, która rozszerza IObject.

class IObject 
{ 
    ... 
} 

class ObjectType1 : IObject 
{ 
    ... 
} 

class ObjectType2 : IObject 
{ 
    ... 
} 

class FooBar 
{ 
    void Foo (ObjectType1 obj); 
    void Foo (ObjectType2 obj); 
} 

Teraz dla mnie oczywistym rozwiązaniem jest wykorzystać dynamiczne wiązanie poprzez umieszczenie metoda Foo wewnątrz poszczególnych klas, które automatycznie wybrać przy starcie prawidłowe Foo do wykonania. Jednak jest to opcja tutaj , a nie, ponieważ definiuję wiele modeli działania na tych obiektach i wolałbym raczej enkapsulować każdy indywidualny model do obsługi obiektów w jego własnej klasie, niż wrzucać wszystkie modele do klasy obiektów.

Znalazłem this post, który pokazuje, jak używać słownika do dynamicznego wybierania w czasie wykonywania poprawnej implementacji metody. W porządku z tym podejściem; jednak przypuśćmy, że muszę wykonać taką ekspedycję w każdym modelu. Jeśli mam tylko IObject i jego konkretne implementacje, czy istnieje sposób uogólnienia tego podejścia, tak żebym mógł nazwać metody o dowolnej nazwie w oparciu o typ środowiska wykonawczego obiektów?

Wiem, że jest to prawdopodobnie niejasne pytanie, ale byłbym wdzięczny za każdą pomoc.

Odpowiedz

10

dynamic słowo kluczowe jest rzeczywiście bardzo dobry w tym:

void Main() 
{ 
    var foobar = new FooBar(); 
    foreach(IObject obj in new IObject[]{ new ObjectType1(), new ObjectType2()}) 
    { 
     foobar.Foo((dynamic)obj); 
    } 
    // Output: 
    // Type 1 
    // Type 2 
} 

class IObject 
{ 
} 

class ObjectType1 : IObject 
{ 
} 

class ObjectType2 : IObject 
{ 
} 

class FooBar 
{ 
    public void Foo (ObjectType1 obj) { 
     Console.WriteLine("Type 1"); 
    } 
    public void Foo (ObjectType2 obj) { 
     Console.WriteLine("Type 2"); 
    } 
} 

Kod jest super proste, a to musi pretty decent performance.

+0

To jest właściwa odpowiedź, myślę. – Ziffusion

+1

Oh wow, jeśli zachowuje się tak, jak wygląda, to jest wspaniałe! Będę się trochę bawił, gdy dostanę jakąś szansę, ale dzięki za to rozwiązanie. W moim kodzie skupiam się na czytelności i łatwej konserwacji, więc wygląda to naprawdę niesamowicie. – TSM

2

Może chcesz coś bardzo zbliżonego do visitor patter.

Jeśli chcesz po prostu wybrać metodę (Foo) obiektu (FooBar) według rodzaju argumentu można użyć refleksji uzyskać wszystkie metody z podanej nazwie (Foo) i zrobić ręczne dopasowanie argumentu na podstawie typu obiektu (ObjectTypeX) i wybór argumentu. Nie zapomnij poprawnie obsługiwać klas pochodnych.

Aby uniknąć ponoszenia kosztów refleksji przy każdym połączeniu - wyniki pamięci podręcznej (np. Budując/kompilując drzewo wyrażeń).

Należy zauważyć, że na początku słownik (działania dla danej metody indeksowanej według typu) będzie łatwiejszy do obsługi/debugowania. Później, jeśli uznasz to za wolne, możesz zastąpić je czymś bardziej skomplikowanym, jak odbicie.

+0

Ciekawe, dzięki za informację zwrotną!Jestem delikatnie zaznajomiony z wyglądem gości, ale jestem bardzo nowy w C# i po prostu odkrywam wszystkie moje opcje. – TSM

0

można po prostu zrobić jedną metodę, która pobiera typ interfejsu, a następnie sprawdzić, czy correcttype i zarzuć

ObjectType1 obj1 = new ObjectType1(); 

foo(obj1); 

void foo(IObject fm) 
     { 
      ObjectType1 cls; 
      if (fm is ObjectType1) 
      { 
       cls = fm as ObjectType1; 
       cls.ID = 10; 
       MessageBox.Show(cls.ID.ToString() + " " + cls.GetType().ToString()); 
      } 
     } 

To dlatego zajęcia wdrożyć IObject , cls.ID to tylko przykład można umieść jedną nieruchomość, którą zaimplementujesz. Proszę, wypróbuj i daj mi znać ... najlepsze życzenia.

+0

To było podejście, które zostało zrobione kilka dni wcześniej (ponieważ jestem zaznajomiony z nim i potrzebowałem pracy demo). Teraz, gdy zajmuję się tym problemem na szerszą skalę, badam inne, prostsze opcje, które mogą być specyficzne dla języka C#. Takie podejście jednak działa! – TSM

Powiązane problemy