2010-10-29 13 views
15

Załóżmy, że masz dwie różne klasy C# A i B, które nie wywodzące się z tej samej klasy bazowej mają takie same nazwy dla metod. Na przykład obie klasy mają metodę connect i disconnect, a także kilka innych. Chcę móc napisać kod, który będzie działać z obydwoma typami.Kod C# do obsługi różnych klas o tych samych nazwach metod

Oto uproszczony przykład tego, co chciałbym zrobić:

public void make_connection(Object x) 
{ 
    x.connect() ; 
    // Do some more stuff... 
    x.disconnect() ; 
    return ; 
} 

Oczywiście, to nie skompilować jako klasa obiektu nie ma metody connect lub disconnect.

Czy istnieje sposób, aby to zrobić?

AKTUALIZACJA. Powinienem był to jasno powiedzieć od samego początku: mam tylko biblioteki DLL dla A i B, a nie źródła.

+5

Jest to dość dużo jak każdy uczy się, jak cenna jest konstrukt interfejs. Naprawdę musisz trafić w sytuację, w której są one przydatne, zanim je "zdobędziesz". –

Odpowiedz

26

Można użyć interfejsu do osiągnięcia tego, co chcesz zrobić.

interface IConnectable 
{ 
    void Connect(); 

    void Disconnect(); 
} 

Zarówno A i B powinny wdrożyć IConnectable. Następnie użyj IConnectable zamiast Object jako typ parametru dla twojej metody i powinieneś wszystko ustawić.

public void MakeConnection(IConnectable connectable) 
{ 
    connectable.Connect(); 

    // Do some more stuff... 

    connectable.Disconnect(); 
} 

Edit: Skoro nie masz kodu źródłowego, masz kilka opcji:

  1. roztwór użytkowy Maxa z użyciem słowa kluczowego dynamic (jeśli używasz .NET 4.0) rozwiązanie
  2. Skorzystaj Steve'a korzystania odlewanie i if/else oświadczenia
  3. tworzenia klas otoki dla A i B i mają je implementować interfejs (lub zdrowym abstrakcyjna klasa podstawowa dla nich)

Na przykład:

class AWrapper : IConnectable 
{ 
    private A obj; 

    public AWrapper(A obj) 
    { 
     this.obj = obj; 
    } 

    public void Connect() 
    { 
     this.obj.Connect(); 
    } 

    public void Disconnect() 
    { 
     this.obj.Disconnect(); 
    } 

    // other methods as necessary 
} 

(BWrapper byłaby podobna, tylko przy użyciu B zamiast A)

Następnie można utwórz opakowania i przekaż je do MakeConnection. Od ciebie zależy, jak chcesz to zrobić. W zależności od sytuacji jedna metoda może być łatwiejsza niż inne.

+3

Będąc pedantyczny tutaj, ale klasy nie * dziedziczą * interfejsów, * implementują * je. – Phil

+0

@Phil: Dzięki! Naprawiony. –

+2

W jaki sposób wprowadzasz interfejs A i B, jeśli nie posiadasz kodu źródłowego A i B? – rlandster

2

Spróbuj użyć raczej interfejsu.

Wystarczy popatrzeć na interface (C# Reference) i Interfaces (C# Programming Guide)

Więc coś

public interface IConnections 
{ 
    void connect(); 
    void disconnect(); 
} 

public class A : IConnections 
{ 
    public void connect() 
    { 
     //do something 
    } 

    public void disconnect() 
    { 
     //do something 
    } 
} 

public class B : IConnections 
{ 
    public void connect() 
    { 
     //do something 
    } 

    public void disconnect() 
    { 
     //do something 
    } 
} 

public void make_connection(IConnections x) 
{ 
    x.connect(); 
    // Do some more stuff... 
    x.disconnect(); 
    return; 
} 
1

Jest to koncepcja OOAD z „programe do interfejsu nie do implementacji” którego możemy uniknąć łańcuch dziedziczenia hierarchii

1- Można utworzyć interfcae

interface IConnection 
{ 
    void Connect(); 
    void Disconnect(); 
} 

2 - Pozwól swoim klasom wdrożyć ten interfejs, jak pokazano poniżej.

class A : IConnection 
{ 
    #region IConnection Members 

    public void Connect() 
    { 
     // your connect method implementation goes here. 
    } 

    public void Disconnect() 
    { 
     // your disconnect method implementation goes here. 
    } 

    #endregion 
} 


class B : IConnection 
{ 
    #region IConnection Members 

    public void Connect() 
    { 
     // your connect method implementation goes here. 
    } 

    public void Disconnect() 
    { 
     // your disconnect method implementation goes here. 
    } 

    #endregion 
} 

3- Po zakończeniu implementacji można ustawić funkcję akceptującą argument połączenia, jak pokazano poniżej.

public void makeConnection(IConnection con) 
    { 
     con.Connect(); 
     con.Disconnect(); 
    } 

4- A z kodu klienta można przekazać obiekt klas, który implementuje interfejs IConnect.

0

Albo trzeba będzie użyć interfejsu (lub klasy Base), jak pokazano przez Zacha i Astander, lub będziesz musiał przypadku obiekt przed użyciem:

public void make_connection(Object x) 
{ 
    ((A)x).connect() ; 
    // Do some more stuff... 
    x.disconnect() ; 
    return ; 
} 
1

Jeśli roztwór interfejs nie jest możliwe (np. nie masz kodu źródłowego), innym mniej skutecznym rozwiązaniem jest użycie refleksji.

+0

+1 dla dodatkowego rozwiązania do zastosowania w przypadku, gdy standardowe podejście (interfejs) nie jest możliwe. – VitalyB

12

ta będzie działać w C# 4:

public void make_connection(dynamic x) 
{ 
    x.connect() ; 
    // Do some more stuff... 
    x.disconnect() ; 
    return ; 
} 
+2

+1, aby być bardziej bezpieczny dla wszystkich, można mieć mocno wpisane publiczne metody - 'make_connection (A)), które delegują do prywatnej metody dynamicznej. –

0

Można również użyć refleksji do wywołania metody

1

Jak mówili inni, re-factoring używać interfejsów lub za pomocą dynamicznego podejścia są prawdopodobnie najbardziej eleganckie sposoby.

Jeśli nie jest to możliwe, możesz rzucić obiekt na swoje typy. Sugerowałbym użycie as, a następnie sprawdzenie, czy rzutowanie działało, niezaznaczone rzutowanie byłoby niebezpieczne, gdyby ktoś zadzwonił do tego typu, którego nie udało się rzucić.

E.g. Jeśli typy A i B obie mają to metoda zwana DoSomething() to będzie działać ...

public static void CallDoSomething(object o) 
    { 
     A aObject = o as A; 

     if (aObject != null) 
     { 
      aObject.DoSomething(); 
      return; 
     } 

     B bObject = o as B; 

     if (bObject != null) 
     { 
      bObject.DoSomething(); 
      return; 
     } 
    } 

ALE to dość brzydki szczerze mówiąc ... ja naprawdę spróbować i byłaby do interfejsów.

0

Co chcesz, nazywa się Duck Typing.

Z Wikipedii:

Duck wpisując to styl dynamicznego typowania w którym prąd ustawić obiektu metod i właściwości określa poprawnych semantykę, niż jego spadku z danej klasy lub realizację partnerstwa określony interfejs.

C# 4.0 pozwala na to, a drugi powiedział, używając dynamiczny słowa kluczowego

Powiązane problemy