Click here to Skip to main content
15,891,657 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
Hello,

I have a class library that deals with Autodesk Vault. This library will acquire a license and release a license, download and upload files and do other things. I instantiate this class from a main form. I want to communicate what the methods this class is doing to the user. For example: this class might be downloading 25 folders, I want to tell the user which folder is presently being downloaded. Or, if a license is unavailable, the "getLicense" method will automatically loop every 60 seconds until a license is acquired. I want to inform the user that the process may be delayed until a license is available. So, what is the best way to go about this?

Thank you,

Eric
Posted
Comments
I.explore.code 2-Oct-12 12:23pm    
Web forms or win forms?

There are two ways to do this.

Pass the parent object to the child object and call a method on the parent.

C#
public class MyForm : Form
{

  private MyWorker _worker;

  public MyForm()
  {
    _worker = new MyWorker();
  }

  public void PassMessage(string message)
  {
    //display message
  }
}

public class MyWorker
{
  private Form _form;
  public MyWorker(Form form)
  {
    _form = form;
  }

  public void doWork()
  {
    //do your work
    _form.PassMessage("My message");
  }
}


Passing in the parent object as a form irreversibly links the child component to a form. You could create an interface to allow the worker to become reusable.

C#
public interface IMessageProcessor
{
  void SendMessage(string message);
}

public class MyForm : Form, IMessageProcessor
{

  private MyWorker _worker;

  public MyForm()
  {
    _worker = new MyWorker();
  }

  public void PassMessage(string message)
  {
    //display message
  }
}

public class MyWorker
{
  private IMessageProcessor _messageProcessor;
  public MyWorker(IMessageProcessor  messageProcessor)
  {
    _messageProcessor = messageProcessor;
  }

  public void doWork()
  {
    //do your work
    _messageProcessor.PassMessage("My message");
  }
}


Using interface/abstract classes in this way is a technique called inversion of control, or IOC, sometimes also known as dependency injection.

Another way is to use events. The child object has an event which bubbles the message back up to the parent class.

C#
public class MyForm : Form
{
  private MyWorker _worker;
  public MyForm()
  {
    _worker = new MyWorker();
    _worker.OnNewMessage += new MyWorker.NewMessageHandler(_worker_OnNewMessage);
  }

  public void _worker_OnNewMessage(string message)
  {
    //display message
  }

}

public class MyWorker
{

  public delegate void NewMessageHander(string message);
  public event NewMessageHander OnNewMessage;

  public void doWork()
  {
    //do your work
    if(OnNewMessage != null)
      OnNewMessage("My message");
  }

}
 
Share this answer
 
v3
Comments
Sergey Alexandrovich Kryukov 2-Oct-12 13:09pm    
I basically like the solutions, especially with reference to the inversion control, but a link would be helpful.
One little problem: your underscored names violate pretty good Microsoft naming conventions. Camel case starting from lo-case could be the ideal choice.
Also, "private" is default, no need to write it, but this is the matter of individual taste; also, perhaps you wanted to emphasize "privacy" to OP.
More importantly, some "public" could be replaced with "internal", because mostly likely you deal with forms in the same assembly. One should not give more access than really required. Overall, I still voted 5.

After all, I added the link to the inversion of control, please see my answer. It was a good your idea to use it.
--SA
Stephen Hewison 2-Oct-12 13:26pm    
Hi Sergey, thanks for the info. Prefixing private fields with underscore is acceptable whilst not often done in C#. I prefer it to lower camel case to avoid clashes with method parameters and having to prefix references to private fields with "this". You are right that depending on the situation, internal would be a valid option for the worker. But then you'd be making the assumption the worker is in the same assembly as the form, the OP didn't give enough info to make this assumption and in reference to using IOC, doing so in the same assembly kind of negates the need for IOC. Also the OP wasn't asking for lesson on access modifiers so I assumed it was out of scope of the question. And whilst it's by the by, you voted 4 not 5.
Sergey Alexandrovich Kryukov 2-Oct-12 14:08pm    
Apparently, one of the two was make mistake. In this case, my 4 was mistake, and I think 5 was correct, so I made it consistent :-)
Thank you.
--SA
Herrwolf1 2-Oct-12 13:39pm    
Thank you for your thorough answer. I went with the IOC method. I had to supply the keyword: "this" as the constructor argument. Not sure why. Doesn't "this" refer to the entire form class? To help me understand the "why", could you expound upon this enigma?
Stephen Hewison 2-Oct-12 13:44pm    
If you have multiple cascading constructors "this" allows you to reference other constructors within the same class as opposed to "base" which allows you reference constructors from the inherited class. So:

public class Foo
{
public Foo()
: this("default text")
{
}

public Foo(string message)
{
//do something with message
}
}
Set up public properties which indicate current download, and so forth, and have a Status property which indicates what is happening at the moment. I would also have at least one Event - StatusChanged, and possibly a NewFolderAvailable event as well. Probably, you will want to provide an Async method which uses a background worker and signals the events, rather than locking the user method, which could freeze the UI as well.
 
Share this answer
 
In addition to the answer by Stephen, Solution 1: this is really good to read:
http://en.wikipedia.org/wiki/Inversion_of_control[^].

[EDIT: Credit to Stephen (please see his comment below):]

It's also great to read on the wider set of SOLID principles explained here:
http://en.wikipedia.org/wiki/SOLID_%28object-oriented_design%29[^].

And everything mentioned in the "See also" section of this article is just must-read of every developer!

—SA
 
Share this answer
 
v4
Comments
Stephen Hewison 2-Oct-12 13:36pm    
Just to add a little more info. IOC or Dependency Injection is one of a set of 5 principles called the SOLID principles. By following these principles in your code design you'll produce very clear, well defined and reusable code. http://en.wikipedia.org/wiki/SOLID_(object-oriented_design)
Sergey Alexandrovich Kryukov 2-Oct-12 14:05pm    
Thank you very much for this note.
I even added it to my answer, just to make it look more SOLID :-), all credit goes to you, of course.
--SA

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900