Please, sorry for the long text.
I have a library of C# Classes which retrieves information from various systems, invokes external functions, validates this info and generates results of the validation to a file. This library can indistinctly be invoked from: 1) a DOS console program, 2) from a Windows form or 3) from a windows service program.
Users have asked me for modifying the library so it can run in a verbose way, i.e. to show the date and time at certain steps, to briefly explain what a certain step or method is doing, etc. They also asked me for introducing exception handling and show error messages.
If I execute in console mode, I should show the messages on the console, if I execute from a Windows form I should send the messages to a message box or to a text box, and if I run from a Windows Service I should send the messages to a log file.
I have 2 questions:
1) How should I modify the C# Classes so I can avoid the constant evaluation:
If program is in console mode writeline…..
Else if program is in windows forms mode messagebox or textbox.text …
Else if program is invoked from a windows service program writelogfile….
2) If the above evaluation is unavoidable, how can I know if the library of C# classes is being invoked by a console, windows form windows service program?
Thanks!!
Possible solution:
I read a little about MS Enterprise Library and … it is too much for my modest requirement so I went for the pragmatic solution of Reed.
I share the way I solved the user requirements, it is a preliminary model before applying to the real situation so, before accepting the Reed solution, your comments to improve and learn are really welcome.
1) I created a little library to define all possible outputs, in this case I defined only the outputs to a console and to a WPF form:
namespace diClass
{
public interface IVerbose
{
void show(string msg, object textBox);
void notify(string msg);
}
public class ConsoleOutput : IVerbose
{
public void show(string msg, object textBox)
{
System.Console.WriteLine(msg);
}
public void notify(string msg)
{
System.Console.WriteLine("Notif: " + msg);
}
}
public class WpfOutput : IVerbose
{
public void show(string msg, object textBox)
{
TextBox tb = (TextBox)textBox;
tb.Text += msg + "\r\n";
System.Windows.Forms.Application.DoEvents();
}
public void notify(string msg)
{
MessageBox.Show(msg);
}
}
public class Output
{
IVerbose outputType;
public IVerbose verboseType
{
get { return outputType; }
set { outputType = value; }
}
public void show(string msg, object textBox)
{
outputType.show(msg, textBox);
}
public void notify(string msg)
{
outputType.notify(msg);
}
}
}
2) Then I defined a console program which uses the above library:
class Program
{
static void Main(string[] args)
{
IVerbose verboseType = (IVerbose)Activator.CreateInstance(typeof(diClass.ConsoleOutput));
Output o = new Output();
o.verboseType = verboseType;
object textBox1 = null;
o.show(string.Format("{0}: Reading Accountig data", DateTime.Now.ToString("dd/MM/yy hh:mm:ss")), textBox1);
o.notify(string.Format("{0}: Application error", DateTime.Now.ToString("dd/MM/yy hh:mm:ss")));
}
}
3) Finally I defined a WPF program which also uses the above library:
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
private void button1_Click(object sender, RoutedEventArgs e)
{
IVerbose verboseType = (IVerbose)Activator.CreateInstance(typeof(diClass.WpfOutput));
Output o = new Output();
o.verboseType = verboseType;
o.show(string.Format("{0}: Reading Accountig data", DateTime.Now.ToString("dd/MM/yy hh:mm:ss")), textBox1);
o.notify(string.Format("{0}: Application error", DateTime.Now.ToString("dd/MM/yy hh:mm:ss")));
}
}
In programs 2) and 3) the last two lines of code are equal, there is no ifs and, that is what I wanted as answer.
Regards.
My preference, for this type of situation, is to make a set of interfaces, and work against the interfaces. You can then use Dependency Injection to inject a concrete version of the interface depending on whether you’re running in console, gui, or as a service. Something like (this is a very simple version):
Then, let’s take the console application version. You just need to provide the correct
IAlgorithmFactoryfor a console app:When your program runs as a console, you’d provide it a
ConsoleAlgorithmFactory, and it would just use it as anIAlgorithmFactory. You can call the methods on it to report progress, and your main program doesn’t care how it’s run – it just reports as needed.When you run as a GUI, on the other hand, you’d make something like
WindowsFormsAlgorithmFactory, pass it in, and now the reporting would be done via forms… Nothing in your program changes.