针对已知方法的程序,而不是类型

时间:2015-02-19 21:14:23

标签: c# .net

假设我有一个类A,它将被编译成dll以便稍后使用。但是我后来知道,我不知道它的类型的类B的一些方法必须在A类中调用。唯一的线索是方法的名称。

让我们说这是班级A

public class A
{
    A(Object instanceOfClassB)
    {
          //stuff...
    }

    public void SendProcessedString()
    {
         //some strings has been processd, I know that class B is going
         //to have a public method like ReceiveData(string data){/*---*/}
         instanceOfClassB.ReceiveData(data);
    }
}

让我们说这是类B,碰巧是WinForm:

public B : Form
{
     public void ReceiveData(string data)
     {
          textBox.Append(data + Environment.NewLine);
     }
}

这种方法是否可行/推荐?

5 个答案:

答案 0 :(得分:5)

是的,可以使用dynamic关键字(在C#4.0或更高版本中)。查看MSDN documentation了解详情。

然而,这会导致令人难以置信的松散编程,并且可能导致难以调试的运行时问题。你最好创建一个B类将实现的接口。

public class A
{
    A(IDataReceiver instanceOfClassB)
    {
          //stuff...
    }

    public void SendProcessedString()
    {
         //some strings has been processd, I know that class B is going
         //to have a public method like ReceiveData(string data){/*---*/}
         instanceOfClassB.ReceiveData(data);
    }
}

public B : Form, IDataReceiver
{
     public void ReceiveData(string data)
     {
          textBox.Append(data + Environment.NewLine);
     }
}

public interface IDataReceiver
{
    void ReceiveData(string data);
}

答案 1 :(得分:2)

你应该使用界面。 B类必须实现“MyInterface”接口,“MyInterface”应该有预期A调用的方法。

public class A
{
    A(MyInerface instanceOfClassB)
    {
          //stuff...
    }

    public void SendProcessedString()
    {
         //some strings has been processd, I know that class B is going
         //to have a public method like ReceiveData(string data){/*---*/}
         instanceOfClassB.ReceiveData(data);
    }
}

如果无法在B类实现接口,则需要使用反射。请参阅此处(How to use reflection to call method by name),了解如何从Type调用方法(因此您必须在A的构造函数中传递类型。

答案 2 :(得分:2)

听起来你需要使用interface。 可以找到关于interfaces的一些信息here

基本上您想要创建interface并将其作为class A的参数并在class B中实施:

interface IDataReceiver
{
    void ReceiveData(string data);
}

然后class B decleration将如下所示:

public B : Form, IDataReceiver

和A类构造函数:

A(IDataReceiver dataReceiver)
{
    //stuff...
}

答案 3 :(得分:2)

这里的另一个选择是使用事件。让你举起一个事件而不是调用回调。

原谅我的C#,我有点生疏

public class classA {
    public event DataReceived(string data);

    public void SendProcessedString() {
        // you got var data from somewhere
        DataReceived(data)
    }
}

然后从您的classB订阅该事件

// classB setup code or initializer:
instanceA.DataReceived += dataReceivedHandler;

private void dataReceivedHandler(string data) {
    // do something with the data.
}

答案 4 :(得分:1)

另一种方法是使用适当的回调 - 只有在保证单个订户的情况下。如果您需要多个订阅者,请使用活动。

public class classA {
    public Action<string> DataReceivedCallback = null;

    public void SendProcessedString() {
        if (null != DataReceivedCallback) { DataReceivedCallback.Invoke(data); }
    }
}

在classB

中的某个地方
instanceA.DataReceivedCallback = new Action<string>(dataReceivedHandler);

private void dataReceivedHandler(string data) {
    // do something with the data.
}