1

I have two Projects one is a Winform application another is a Class library. I have added a reference to the class Library in Winform and called a method of the class library. Now I want to call a different method in winform application from class library but I can't add a reference to winform to the class library.

IN CODE:-

public partial class Form1 : Form
    {
        private void btn_Click(object sender, EventArgs e)
        {
            A obj = new A();
            obj.foo();
        }
        public string Test(par)
        {
            //to_stuff
        }


    }

and in Class library

 class A
    {
        public void foo()
        {
            //Do_stuff
            //...

            Test(Par);

            //Do...

        }
    }
David Arno
  • 42,717
  • 16
  • 86
  • 131
too_cool
  • 1,164
  • 8
  • 24
  • You need to re-design it then. If you can provide a compelling example as to why you might need to do this, perhaps we can suggest a different way of approaching it. As it stands, your question is too vague. – Charles Mager Jun 11 '15 at 12:59
  • 1
    The only way is to create a contract assembly, define an interface in it, implement this interface by the form and pass a reference of this interface to the library. Both of your current assemblies could reference this contract assembly. – Sebastian Schumann Jun 11 '15 at 13:00
  • Yup. You're trying to create a circular reference (and a circular dependency in general), which is a terrible idea. Don't do it. Why *would* you ever need to call anything from the winforms project in your class library? – Luaan Jun 11 '15 at 13:00
  • 1
    @Verarind, that is one way, but it's not the only way, eg see my answer. – David Arno Jun 11 '15 at 13:04
  • @DavidArno: Yes you're right. Your solution is an also possible way. But we both did the same mistake. The title says that he want's to call `Test(..)` WITHOUT adding a reference to class A. Hopefully he only tries to avoid a reference to the library. A class reference might be okay. – Sebastian Schumann Jun 11 '15 at 13:07
  • @Verarind, good point, the title made no sense as it was the complete opposite of the code. I've fixed the title therefore. – David Arno Jun 11 '15 at 13:10
  • You could define an event in the class "A" and then subscribe the form to this event. Then just raise the event and call whatever you want in the form class – Davide Lettieri Jun 11 '15 at 14:49

2 Answers2

4

You can achieve this by injecting Test into class A.

For example:

public partial class Form1 : Form
{
    private void btn_Click(object sender, EventArgs e)
    {
        A obj = new A();
        obj.foo(Test);
    }

    public string Test(string par)
    {
        //to_stuff
    }
}

class A
{
    public void foo(Func<string, string> callback)
        //Do_stuff
        //...

        if (callback != null)
        {
            callback(Par);
        }

        //Do...

    }
}
David Arno
  • 42,717
  • 16
  • 86
  • 131
  • @too_cool, short answer: no. For a longer answer, please see http://stackoverflow.com/questions/2082735/performance-of-calling-delegates-vs-methods – David Arno Jun 11 '15 at 13:07
  • No, calling delegates like this is very fast. – Enigmativity Jun 11 '15 at 13:07
  • @DavidArno - Don't forget the `null` check on the callback. – Enigmativity Jun 11 '15 at 13:08
  • @Enigmativity, good point. Also I fixed the code as injecting via the constructor was a distraction to the answer of "use a delegate". – David Arno Jun 11 '15 at 13:15
  • @DavidArno Thx for the help.learned a lot..Just one for doubt can i pass another Form to the Class so that i can access the other form property or methods..and sry for late reply – too_cool Jun 12 '15 at 10:00
  • @too_cool, you should avoid doing that as much as possible as you can end up tightly coupling the two functions, which will make testing harder. However it is legitimate at times and SchlaWiener's answer explains how to do that: by passing the form to `foo` via an interface reference. – David Arno Jun 12 '15 at 12:00
3

While the callback method from David is a sufficient solution, if your interactions gets more complex, I would use this approach

Create an inteface in your class libary

public interface ITester
{
    string Test(string value);
}

Rewrite your code so class A expects an ITester interface

public class A
{
    public A(ITester tester)
    {
        this.tester = tester;
    }

    public string foo(string value)
    {
        return this.tester.Test(value);
    }        
}

Implement your interface in Form1

public partial class Form1 : Form, ITester
{
    private void btn_Click(object sender, EventArgs e)
    {
        A obj = new A(this);
        obj.foo("test");
    }

    public string Test(string value)
    {
        //to_stuff
        return value;
    }
}
Jürgen Steinblock
  • 30,746
  • 24
  • 119
  • 189