2010-10-29 92 views
15

假设您有两个不同的C#类AB,虽然不是从同一基类派生,但它们共享某些方法的相同名称。例如,两个类都有一个connect和一个disconnect方法以及其他几个。我希望能够编写一次适用于这两种类型的代码。处理具有相同方法名称的不同类的C#代码

这里是我想要做的一个简单的例子:

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

当然,因为Object类没有connectdisconnect方法,这并不编译。

有没有办法做到这一点?

UPDATE。我应该从一开始就明确这一点:我只有A和B的DLL,而不是源。

+5

这是几乎每个人如何学习的界面结构是多么宝贵。在“得到它”之前,你确实需要找到他们有用的情况。 – 2010-10-29 05:46:55

回答

26

您可以使用一个接口来完成你想做的事情。

interface IConnectable 
{ 
    void Connect(); 

    void Disconnect(); 
} 

两个AB应该实现IConnectable。然后使用IConnectable而不是Object作为您的方法的参数类型,并且应该全部设置。

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

    // Do some more stuff... 

    connectable.Disconnect(); 
} 

编辑:既然你没有源代码,你有两个选择:

  1. 使用dynamic关键字,(如果你使用的是.NET的应用最大的解决方案4.0)
  2. 使用史蒂夫的使用铸造和if/else报表
  3. AB创建包装类,并有解决方案他们实现接口(或使用通用抽象基类为他们)

例如:

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有异曲同工之处,只是用的AB代替)

然后,你可以创建包装并将它们传递到MakeConnection。这取决于你如何去做。根据你的情况,一种方法可能比其他方法更容易。

+3

在这里迂腐,但类不*继承*接口,他们*实现*他们。 – Phil 2010-10-29 05:30:44

+0

@菲尔:谢谢!固定。 – 2010-10-29 05:31:58

+2

如果您没有A和B的源代码,您如何让A和B实现一个接口? – rlandster 2010-10-29 13:15:13

2

尝试使用接口。

看一看interface (C# Reference)Interfaces (C# Programming Guide)

因此,像

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

有你避免继承链的OOAD概念“长期计划的接口没有实现”这让层次

1您可以创建一个interfcae

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

2 - 让你的类实现这个接口,如下所示。

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-一旦你比,你可以让你的函数接受IConnection的参数,如下图所示的实施完成。

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

4-从客户端代码中,您可以传递实现IConnect接口的类的对象。

0

要么你将不得不使用的接口(或基类)如图扎克和astander,或你将不得不在使用前区分对象:

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

如果接口的解决方案是不可能的(例如你没有源代码),另一个不太有效的解决方案是使用反射。

+0

+1,以便在标准(界面)方法无法完成的情况下使用其他解决方案。 – VitalyB 2010-11-03 22:32:52

12

这将工作在C#4:

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

+1是更安全的类型,你可以使用强类型的公共方法 - 'make_connection(A a)' - 委托给一个私有的动态方法。 – 2010-10-29 18:28:18

0

您也可以使用反射来调用方法

1

正如其他人所说,再保理使用的接口或使用动态的方法很可能是最优雅的方式。

如果这是不可能的,你可以将对象转换为你的类型。我建议使用as,然后检查演员是否工作,如果有人用未能投射的类型调用此演员,则未经检查的演员阵容会很危险。

E.g.如果类型AB都有一个方法叫DoSomething()那么这将工作...

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

这是非常丑陋的,说实话......我真的尝试并重构到接口。

0

你想要什么叫做Duck Typing

维基百科:

鸭打字是动态类型的风格,其中对象的当前设置的方法和属性决定了有效的语义,而不是从一个特定的类或实现其继承具体界面。

C#4.0允许这一点,其他都表示,采用动态关键字

相关问题