Dumbo
Dumbo

Reputation: 14102

program against known method, not the type

Lets say I have a class A which is going to be compiled into a dll to be used later. But I kind of know that later, some methods of class B which I am not aware of its type must be called in A class. The only clue is the name of the methods.

Lets say this is class 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);
    }
}

Lets say this is class B, happen to be a WinForm:

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

Is such approach possible/recommended?

Upvotes: 0

Views: 93

Answers (5)

Sam Axe
Sam Axe

Reputation: 33738

Yet another method is to use a proper callback - only if a single subscriber is guaranteed. If you need multiple subscribers use an event.

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

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

somewhere in classB

instanceA.DataReceivedCallback = new Action<string>(dataReceivedHandler);

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

Upvotes: 1

Sam Axe
Sam Axe

Reputation: 33738

Another option here would be to use events. Have your raise an event instead of invoking the callback.

excuse my C#, I'm a little rusty

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

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

Then subscribe to that event from your classB

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

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

Upvotes: 2

RE6
RE6

Reputation: 2724

It sounds you need to use an interface. A little information about interfaces can be found here.

Basically you want to create an interface and get it as a parameter for class A and implement it in class B:

interface IDataReceiver
{
    void ReceiveData(string data);
}

then class B decleration will look like:

public B : Form, IDataReceiver

And class A` constructor:

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

Upvotes: 2

Yogee
Yogee

Reputation: 1442

You should be using interface. You class B must implement "MyInterface" interface and "MyInterface" should have method which are are expecting A to call.

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

If it is not possible to implement interface at class B, you need to use reflection. See here (How to use reflection to call method by name) on how to call a method from a Type (so you will have to pass the type in constructor of A.

Upvotes: 2

BJ Myers
BJ Myers

Reputation: 6813

Yes, this is possible using the dynamic keyword (in C# 4.0 or higher). Check the MSDN documentation for more info.

However, this leads to incredibly loose programming and can cause runtime issues that are difficult to debug. You're much better off creating an interface that class B will implement.

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

Upvotes: 5

Related Questions