开发者

C# code to handle different classes with same method names

Let's say you have two different C# classes A and B that while not deriving from the same b开发者_如何学运维ase class do share some of the same names for methods. For example, both classes have a connect and a disconnect method, as well as several others. I want to be able to write code once that will work with both types.

Here is a simplified example of what I would like to do:

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

Of course, this does not compile as the Object class does not have a connect or disconnect method.

Is there a way to do this?

UPDATE. I should have made this clear from the start: I only have the DLLs for A and B and not the source.


You can use an interface to accomplish what you want to do.

interface IConnectable
{
    void Connect();

    void Disconnect();
}

Both A and B should implement IConnectable. Then use IConnectable instead of Object as the parameter type for your method and you should be all set.

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

    // Do some more stuff...

    connectable.Disconnect();
}

Edit: Since you don't have the source code, you have a couple of options:

  1. Use Max's solution of using the dynamic keyword, (if you are using .NET 4.0)
  2. Use Steve's solution of using casting and if/else statements
  3. Create wrapper classes for A and B and have them implement the interface (or use common abstract base class for them)

For example:

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 would be similar, just using B instead of A)

Then you could create the wrappers and pass them into MakeConnection. It's up to you how you want to do it. Depending on your situation, one method may be easier than the others.


This will work in C# 4:

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


Try using an Interface rather.

Have a look at interface (C# Reference) and Interfaces (C# Programming Guide)

So something like

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;
}


There is a OOAD concept of 'Programe to an interface not to an implementation' which let's you avoid the chain of inheritance hierarchies

1- You can create a interfcae

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

2- And let your classes implement this interface as shown below.

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- Once you done with the implementation than you can make your function accepting an argument of IConnection as shown below.

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

4- And from your client code , you can pass the object of classes which implements IConnect Interface.


If the interface solution is not possible (e.g you don't have source code), another less effecient solution is to use reflection.


As others have said, re-factoring to use interfaces or using the dynamic approach are probably the most elegant ways.

If this is not possible you could cast the object to your types. I'd suggest using as and then checking that the cast worked, an unchecked cast would be dangerous if someone called this with a type that failed to cast.

E.g. If types A and B both have a method called DoSomething() then this will work...

    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;
        }
    }

BUT this is pretty ugly to be honest... I'd really try and refactor to interfaces.


Either you will have to use an Interface (or Base class) as shown by Zach and astander, or you will have to case the object before using:

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


You could also use reflection to invoke the methods


What you want is called Duck Typing.

From Wikipedia:

Duck typing is a style of dynamic typing in which an object's current set of methods and properties determines the valid semantics, rather than its inheritance from a particular class or implementation of a specific interface.

C# 4.0 allows this, as other have said, using the dynamic keyword

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜