How can I solve this problem with C# classes? - c#

I am creating an application that the user will be able to setup a series of functions to run on an object (image manipulation stuff).
Each different function has either no configurable options, or its own uniques set of options.
This is hard to explain, so let me show a simple example:
Image opened (always happens)
Remove border (two options)
Despeckle image (5 options)
Crop image (10 options)
Save image
The problem is that I need to allow the user to create a custom series of cleanup functions that will be used to process images in bulk.
What is the best way to go about this?

I'd highly recommend you look into the Command Pattern:
http://www.codeproject.com/KB/architecture/Command_Pattern.aspx
Essentially, this involves creating "Command" subclasses for each type of action the user can perform - and pushing them unto a stack once the command has been executed.
Each command knows how to "do" itself, and also "undo" itself.
Thus, undo is a relatively straight forward process of popping commands off the stack, and calling the undo method on them.
Because each instance of a Command can contain it's own state ("options"), you can create exactly the commands you want to use ahead of time, and "batch" them to get the result you are looking for.
pseudo-code:
public class ImageEditor
{
public Stack<Command> undoList = new Stack<Command>();
public void executeCommand(Command command)
{
command.performAction(this);
undoList.push(command);
}
public void undo()
{
undoList.peek().undoAction(this);
undoList.pop();
}
}
public interface ICommand
{
void performAction(ImageEditor editor);
void undoAction(ImageEditor editor);
}
public class CreateBorderCommand : ICommand
{
public int BorderWidth { get; set; }
private Border MyBorderBox { get; set; }
public void performAction(ImageEditor editor)
{
MyBorderBox = new Border(BorderWidth, editor.frame);
editor.addElement(MyBorderBox);
}
public void undoAction(ImageEditor editor)
{
editor.removeElement(MyBorderBox);
}
}
Later on:
ImageEditor editor = new ImageEditor();
editor.executeCommand(new CreateBorderCommand() { BorderWidth = 10 });
...
If you really want, you could make it a little more involved, and make all of the command definitions serializable - allowing you to create a list of them and read in the list and execute them later.

This can be solved by one of the standard 'Gang Of Four' design patterns. You should spend a bit of time reading about the Command Pattern. This pattern allows you to encapsulate the operations performed on an object within classes that implement the same interface. In your example, each of your steps becomes a command. Once you have a common interface for your commands you can then compose them into Macros.

Related

Choosing a Subclass without knowing the name of it in C#

Edit 1:If anyone has a better Title for that, feel free to tell me or edit it yourself.
Edit 2: Thanks for your contribution guys, the answer given is almost what I need with some tweaks and I'm thankful for the small stuff here. Really learnt much today!
Little stuff here that I'm banging my head on for a while now.
I want to create a Slideshow and want the logic in the Image objects itself.
The programm should be able to set a desired transition or just a random one so
I wanted to create a Transition Superclass with the general stuff and spezialize
it in the subclasses. So I have Transitions.cs (with no Code currently inside it)
and no derived class. I want it to be in the way of adding a single .cs file
extending Transitions.cs and not change any other code to implement a new Transition.
The Code I currently have looks something like this but I guess my
description is more helpful than the code
public class SlideImages : MonoBehaviour {
Image image;
Image nextImage;
int tracker;
private void Transition(int ID)
{
/*Something to choose a transition based on the ID
*Transitions.cs is the superclass of all different transitions
*f.e. Ken-Burns Effect, or scattered Transition which all extend from it
*/
}
~SlideImages()
{
//TODO: Pop and Push
}
}
I had the idea of something along the lines of static stuff to workaround that
looks like this but it doesn't work I suppose
public class Transitions : MonoBehaviour {
public static int TransitionID;
protected static int SubclassCount;
protected static void SetID()
{
TransitionID = Transitions.SubclassCount;
Transitions.SubclassCount++;
}
}
I did look into the state design pattern but I don't want to implement it as I just need the state to be chosen once and shortlived. The Image Objects themself only have a lifetime of around a few seconds. I don't want to do the usual if-nesting or just put all the code inside the SlideImages.cs. Is there any good guidance to it or stuff that goes very indepth into inheritance and such stuff?
Appreciate all the input.
There are two straight-forward solutions to what you want to do. Your basic problem is that you want to be able to dynamically add functionality to your program but you don't want to have knowledge of what has been added in order to use it. The most hack-ish way of doing it is to use Actions instead of subclassing. When you want to add another transition you just update an actions list like this:
public static class Transitions
{
private static Action[] TransitionStrategies = new Action[]
{
() => { /* One way of performing a transition */ },
() => { /* Another way of performing a transition */ },
() => { /* Keep adding methods and calling them here for each transition type */ }
}
public static void PerformTransition(int? transitionIndex = null)
{
int effectiveIndex;
// if the transition index is null, use a random one
if (transitionIndex == null)
{
effectiveIndex = new Random().Next(0, TransitionStrategies.Length);
}
else
{
effectiveIndex = transitionIndex.Value;
}
// perform the transition
TransitionStrategies[effectiveIndex]();
}
}
The above approach is simple but all of the logic (or at least references to the logic depending on where you implement the actual work for the transitions) is in one place. It also has the potential to get quite messy depending on how many transitions you are adding and how many developers are touching this codebase. It also requires all functionality to be added by someone with access to the full codebase and requires a recompilation each time new transitions are added.
A more complex but much more maintainable and flexible approach in the long term is to use modules (or plugins for our purposes). Each transition in that approach is provided by either a shared module or a specific module and is a subclass of a base AbstractTransition class or an implementation of an ITransition interface depending on how you want to go about doing that. Use post-build tasks to place all of your module dlls in a single directory accessible to your main program (anyone else given permission can put transition module dlls there too). When your program launches, it dynamically loads all dlls from that directory (no recompilation required when new transitions are added as long as the right dlls are in that directory) and pulls out all of the classes implementing that interface. Each of those interface implementations are instantiated and placed into a data structure after which you can use a similar strategy to the above's PerformTransition method to perform a random one or one based on an ID instead of an index. I can edit this question with an example of that structure if you would like.
Edit: You didn't ask for it yet, but here's an example with plugins/modules.
First, create a project to load and run the transitions. This example will use a project called ModuleDemo. Give it a main method like this:
static void Main(string[] args)
{
// create a list to hold the transitions we load
List<AbstractTransition> transitions = new List<AbstractTransition>();
// load each module we find in the modules directory
foreach (string dllFilepath in Directory.EnumerateFiles("Modules", "*.dll"))
// this should really read from the app config to get the module directory
{
Assembly dllAssembly = Assembly.LoadFrom(dllFilepath);
transitions.AddRange(dllAssembly.GetTypes()
.Where(type => typeof(AbstractTransition).IsAssignableFrom(type))
.Select(type => (AbstractTransition) Activator.CreateInstance(type)));
}
// show what's been loaded
foreach (AbstractTransition transition in transitions)
{
Console.WriteLine("Loaded transition with id {0}", transition.TransitionId);
// execute just to show how it's done
transition.PerformTransition();
}
Console.Read(); // pause
}
You'll notice that the method references an AbstractTransition class. Let's create a separate TransitionModule project for that now. This is the project that the modules will reference:
namespace TransitionModule
{
public abstract class AbstractTransition
{
public readonly int TransitionId;
public abstract void PerformTransition();
protected AbstractTransition(int transitionId)
{
TransitionId = transitionId;
}
// you can add functionality here as you see fit
}
}
Now that we have an abstract transition class for the plugins to implement and a functioning plugin loader, we can go ahead and create a few transition plugins.
I created a Modules folder for this in my solution but it doesn't really matter.
First module in a FlipTransition project:
using System;
using TransitionModule;
namespace FlipTransition
{
public class FlipTransition : AbstractTransition
{
public FlipTransition() : base(2)
{
}
public override void PerformTransition()
{
Console.WriteLine("Performing flip transition");
}
}
}
Second module in a SlideTransition project:
using System;
using TransitionModule;
namespace SlideTransition
{
public class SlideTransition : AbstractTransition
{
public SlideTransition() : base(1)
{
}
public override void PerformTransition()
{
Console.WriteLine("Performing slide transition");
}
}
}
Note that each of those projects needs to reference the TransitionModule project but the main project doesn't need to know about any of the other projects.
Now we have 2 transition plugins and a plugin loader. Since the plugin loader is going to load the modules from a Modules directory, go to the /bin/Debug directory of the main project and make a Modules directory. Copy all of the dlls from the /bin/Debug directories of the transition plugin projects into that directory as well. All of this can be automated with post-build tasks later on.
Go ahead and run the program. You should get output like this:
Loaded transition with id 2
Performing flip transition
Loaded transition with id 1
Performing slide transition
There's a lot you can do to make this more elegant, but this is at least a simple example of how you can use a plugin-based architecture to provide what you need.
You could try playing around with abstract classes, create a base abstract class for image transitioning;
public abstract class ImageTransition
{
protected int imageId { get; set; }
public Dictionary<int, Image> ImageDictionary { get; set; }
protected abstract void TransitionToNextImageId();
public Image GetNextImage()
{
TransitionToNextImageId();
return ImageDictionary[imageId];
}
}
You then create new Transition types that inherit from this base class and have their own implementation of the TransitionToNextImageId method;
public class InTurnImageTransition : ImageTransition
{
protected override void TransitionToNextImageId()
{
if(this.imageId < ImageDictionary.Count)
this.imageId ++;
}
}
public class RandomImageTransition : ImageTransition
{
protected override void TransitionToNextImageId()
{
imageId = new Random().Next(0, ImageDictionary.Count);
}
}
This allows you to build up some custom transitions however you wish.
-Edit-
You would of course fill the dictionary ImageDictionary before calling the GetNextImage method.

SOLID and C# events

I'm currently learning the SOLID (OO Design) and something bugs me: the dependency inversion principle, according to which the upper policy layer should be able to comply with a lower one's interface, made me wonder; where do event's fit in?
For example (taken from "Agile Principles, Patterns, and Practices in C#"):
Here, when the button is turned on/off, it calls turnOn/turnOff on the ButtonServer it would have some reference to.
Now if several objects were to depend on one single button, in order for this to work (imo), the button would have to store a list of ButtonServer's and then call on each one's turnOn/turnOff.
This looks to me like reinventing what event already does.
Now if that button were to have a new state, sleep, we'd have to create a new interface ButtonServerSleep (or some other name) and we'd have to store a new different list of each ButtonServerSleep which would be depending on the button*. And will just end up writing the same kind of code for looping through ButtonServer and call turnOn/turnOff than for looping through ButtonServerSleep and call sleep, the kind of code to which event's were made to avoid.
* if this would break the SRP, tell me.
The example with buttons and lamps is quite hard to follow, but I'll try:
public class Button
{
IButtonServer _buttonServer;
private bool _amIOn;
public Button(IButtonServer buttonServer)
{
_buttonServer = buttonServer;
}
void Poll()
{
_amIOn = !_amIOn;
if(_amIOn) _buttonServer.TurnOn(); else _buttonServer.TurnOff();
}
}
interface ITurnOnOffableDevice
{
void TurnOn();
void TurnOff();
}
interface IButtonServer : ITurnOnOffableDevice
{
void RegisterDevice(ITurnOnOffableDevice l);
}
public Lamp : ITurnOffableDevice
{
public Lamp(IButtonServer buttonServer)
{
buttonServer.RegisterDevice(this);
}
public void TurnOn()
{
Shine();
}
public void TurnOff()
{
Darken();
}
}
public MeatTriturator : ITurnOffableDevice
{
public MeatTriturator(IButtonServer buttonServer)
{
buttonServer.RegisterDevice(this);
}
public void TurnOn()
{
Triturate();
}
public void TurnOff()
{
ShutItDown();
}
}
Now, on some DLL which doesn't know about lamps, or meat triturators, you have this:
public ButtonServer : IButtonServer
{
private List<ITurnOnOffableDevice> _devices = new List<ITurnOnOffAbleDevice>();
public void RegisterDevice(ITurnOnOffAbleDevice l)
{
_devices.Add(l);
}
public void TurnOn()
{
foreach(var l in _devices) { l.TurnOn(); }
}
public void TurnOff()
{
foreach(var l in _devices) { l.TurnOff(); }
}
}
Then you create everything:
public static IButtonServer MyLampAndTrituratorButtonServer;
static void Prepare()
{
DependencyInject.ForType<IButtonServer>.Create<ButtonServer>();
}
static void Main()
{
Prepare();
MyLampAndTrituratorButtonServer = DependencyInject.CreateObject<IButtonServer>();
// The MyLampAndTrituratorButtonServer could be injected directly in the
// constructor of these objects, but for clarity I've left the normal
// object declaration
// this button will turn on lamps and meat triturators
var button = new Button(MyLampAndTrituratorButtonServer);
// these lamp and meat tritutator will be turned on/off by
// the buttons in that server
var lamp = new Lamp(MyLampAndTrituratorButtonServer);
var meatTriturator = new MeatTriturator(MyLampAndTrituratorButtonServer);
}
Then somewhere else, deep inside your program, you have the need to create a new button that lights up that lamp and meat triturator, you'd just do:
var button = new Button(MyLampAndTrituratorButtonServer);
No reference whatsoever to the actual lamp, or the meat triturator.
(Or better yet: create the button while injecting the IButtonServer dependency on the constructor parameter (this would depend on your dependency injector, so I'm not giving code), but then you'd neither need the reference to MyLampAndTrituratorButtonServer)
With this, you have decoupled your buttons from your lamps or meat triturators. The action of turning off and on is done by the button server, which as you can
see is injected, so it could be anything (anything that implements IButtonServer).
So you have delegated the responsibility of turning on and off the devices to a single dependency.
Again, in the "real world", buttons tend to do just one thing, and lamps only turn off and on, and this is dubious to change in the future... but this is an example of delegating the responsibility to a single point.
But let's take it a bit further... imagine your requirements have changed, and the buttons which turn on/off lamps and meat triturators (and only those, not all buttons), need to have a security measure. Whenever they are turned on, they need to auto-shutdown in 30 seconds.
With your "events based approach", you would need to derive one object from "button" (i.e., ButtonThatTurnsOffAt30secs : Button) and change -everywhere- where a lamp or meat triturator is created, then recompile.
With the isolated dependency, you'd just rewrite your buttonserver:
public ButtonServerThatTurnsOffAt30seconds : IButtonServer
{
private List<ITurnOnOffableDevice> _devices = new List<ITurnOnOffAbleDevice>();
public void RegisterDevice(ITurnOnOffAbleDevice l)
{
_devices.Add(l);
}
public void TurnOn()
{
foreach(var l in _devices) { l.TurnOn(); new Timer(30, () => { TurnOff(); } }
}
public void TurnOff()
{
foreach(var l in _devices) { l.TurnOff(); }
}
}
And change your dependency injection:
DependencyInject.ForType<IButtonServer>.Create<ButtonServerThatTurnsOffAt30seconds>();
If you have separated your project right, you wouldn't even need to recompile the whole application, just a single DLL change (or two if you have the dependency injector bootstrap on a different one) and voilá, now all your lamps and meat triturators turn off at 30 seconds.
Again, this is not the best example, and it made making an example hard, but I hope you can follow.
As a disclaimer: I'm trying to make a value on dependency isolation, not aiming to explain SOLID principles or any pattern, since you seem confused on that. I myself don't "follow patterns blindly", I just find whatever I find interesting on all those patterns and use it for a good purpose.
If you are sure your buttons will never change (or ALL your buttons will change at the same time), then there's no need for all of these. Whether going full-throttle on this, or whether to apply the GTD (Getting Things Done) principle, is up to you.
Applying patterns, decoupling dependencies, etc., takes time and effort, and depending on the project, deadline, budget, and possibility of it changing in the future, they are worth implementing or not.

Where to create the class

I'm trying to model a production system with "facility" as Class and some subclasses down to "Activity". The facility has a name as only parameter (at the moment), and I'd like to create an instance of the class reading the name as an input from a textbox. Since "activity" is inherit the properties from it's "parent classes" I'll create an instance of the class "activity" and not it's parent.
The problem is that I don't know where to create the class and how to pass it so that when I add the first subclass "Workstation" I can edit the properties of the same "activity" I created earlier.
I don't really have any code to add at this point unfortunately, but please tell me if there's anything special you'd like to see and I'll try to add it to the post.
And by the way, it's in the shape of a WinForm application with a GUI I'm trying to do this.
There are a couple things to note here. First, you'll want to use the Composite pattern to encapsulate the relationships between your classes. (For those who don't understand the OP's type hierarchy, it does make perfect sense in a factory context. There are many activities going on, which can be grouped into workstations and at a higher level into facilities.)
So, you should probably have a base Activity class (that supports the Composite pattern by exposing a collection of child activities), and then your "levels" (like Facility and Workstation) will inherit from Activity. Each of these classes will have unique properties.
The following classes should be created in their respective files, e.g. Activity.cs, Factory.cs, Workstation.cs:
class Activity
{
// An attribute that every Activity may need: a displayable name.
// This might be useful if you have a TreeView, e.g., showing all the activities.
public string Name { get; private set; }
// Every Activity could have child activities - this is the Composite pattern.
// You can loop through these to navigate through the hierarchy of your data.
// (This is often done using recursion; see example below with GetAllWorkstations().)
public List<Activity> ChildActivities { get; private set; }
public Activity()
{
ChildActivities = new List<Activity>();
}
public override string ToString() { return Name; }
}
class Factory : Activity
{
public string City { get; private set; }
public string Address { get; private set; }
}
class Workstation : Activity
{
public string WorkstationNumber { get; private set; }
}
The responsibility of loading your model then has to be handled somewhere. A good place to do it is in your main form. For example, you might write code like this:
class MainForm : Form
{
private readonly List<Factory> topLevelFactoryActivities;
public MainForm()
{
// ... other code
topLevelFactoryActivities = LoadTopLevelFactoryActivities();
}
private IEnumerable<Factory> LoadTopLevelFactoryActivities()
{
var factories = new List<Factory>();
// TODO: Load the factories, e.g. from a database or a file.
// You can load all the child objects for each factory here as well,
// or wait until later ("lazy-loading") if you want to.
// NOTE: If this becomes complex, you can move the LoadTopLevelFactoryActivities()
// method to its own class, which then becomes your "data access layer" (DAL).
return factories;
}
}
Now, if you want to find all the workstations that are part of a particular factory, you would write a method like the following on the Factory class:
class Factory : Activity
{
// ... other code
public IEnumerable<Workstation> GetAllWorkstations()
{
return GetWorkstationsRecursive(this);
}
private IEnumerable<Workstation> WorkstationsIn(Activity parentActivity)
{
foreach (var workstation in parentActivity.ChildActivities.OfType<Workstation>)
{
// Uses a C# feature called 'iterators' - really powerful!
yield return workstation;
}
foreach (var childActivity in parentActivity.ChildActivities)
{
// Using recursion to go down the hierarchy
foreach (var workstation in WorkstationsIn(childActivity))
{
yield return workstation;
}
}
}
}
You would call it like so, e.g. in your main form:
class MainForm : Form
{
// ... other code
public MainForm()
{
// ... other code
// Assume this is assigned to the factory that you want to get all the workstations for
Factory myFactory;
var workstations = myFactory.GetAllWorkstations();
// Now you can use 'workstations' as the items source for a list, for example.
}
}
As an example use case, you might want to show a second form (that belongs to the main form) which shows a list of all the workstations. (In practice you probably shouldn't create too many windows; prefer building a nonoverlapping layout. But just to show how you might pass the model instances around...)
class WorkstationListForm : Form
{
private IEnumerable<Workstation> workstations;
public WorkstationListForm(IEnumerable<Workstation> workstations)
{
this.workstations = workstations;
//TODO: You can now use 'workstations' as the ItemsSource of a list view in this form.
}
}
You could, of course, make topLevelFactoryActivities public on your MainForm and pass the variable this of the MainForm to the WorkstationListForm constructor instead. Then you could access the member on MainForm like this:
public WorkstationListForm(MainForm mainForm)
{
var topLevelFactoryActivities = mainForm.topLevelFactoryActivities;
// Now WorkstationListForm has full access to all the data on MainForm. This may or
// may not be helpful (it's usually best to minimize sharing and public fields).
}
Second, you'll want to use a proper separation between your view (user interface code/classes) and your model (the Activity hierarchy).
Third, if there's going to be any kind of live data being pushed to the user interface then you'll need a databinding mechanism to automatically update the view whenever the model changes.
In general, #2 & #3 are popularly addressed via the Model-View-ViewModel pattern. There is an excellent tutorial here for building an MVVM app using WinForms/C#.
That should get you started, at least. Also see an answer to a similar question. (Sorry about promoting my own answer, but I don't want to type out the whole example twice. Please forgive me. :))

Multiple Decorators in Decorator Pattern

I have read a few tutorials on the topic of the Decorator Pattern similar to this one. The basic example is a cake as in this tutorial, or a pizza as in other tutorials, and the decorators usually pass through values and modify them on the way (as in, every PizzaDecorator adds a small amount onto the price, thus returning the price of the pizza + all decorators). Now, that's certainly a nice example, but I am having a little trouble applying this to a less edible problem.
Suppose I have a base class that takes an input, according to which it modifies its state. Some of these state modifications cause an event to be raised which passes a value that could be considered the output. Now suppose the following features I'd like to individually add as decorators:
A buffer for the output
A history of the input
Another type of input (e.g. interprets a set of characters as allowed byte input values)
Individually, they are not so much of a problem. The basic functionality of the class (i.e. the TakeInput(byte input) and event Handler OutputAvailable) reside in an interface that the base class as well as the decorators can inherit (do I really need the extra abstraction layer as in the given example, i.e. a separate interface for the Decorator classes which in turn inherits from the base interface?). Now, if I implement the input cache in a decorator, how do I add it in such a way, that the next decorator would not hide it again? If I added, say, a list to simply store the input and made it available via a property, that property would be hidden should I decide that I also want the output buffered. I could keep references to both decorators around- but that would be rather messy, or so I think, because I am going to need quite a bunch of decorators. If I derived from the Decorator, the inheritance mess that I initially wanted to avoid by applying this pattern would not go away. How do I solve this problem?
As requested, a piece of code that illustrates my problem. (Or so I hope, anyway)
public interface ISampleClass
{
event OutputHandler OutputAvailable;
void TakeInput(byte input);
}
public class BaseSampleClass : ISampleClass
{
public event OutputHandler OutputAvailable;
void TakeInput(byte input)
{ // To keep things simple:
this.OutputAvailable(input);
}
}
public class SampleClassInputCacheDecorator : ISampleClass
{
private ISampleClass decoratedClass;
private List<byte> inputCache;
public event OutputHandler OutputAvailable;
public SampleClassInputCacheDecorator(ISampleClass decoratedClass)
{
this.decoratedClass = decoratedClass;
this.decoratedClass.OutputAvailable += (output) => {
this.OutputAvailable(output);
};
}
public List<byte> InputHistory { get { return this.inputCache; } }
public void TakeInput(byte input)
{
this.decoratedClass.TakeInput(input);
}
}
public class SampleClassCharInputAdapterDecorator : ISampleClass
{
private ISampleClass decoratedClass;
public SampleClassCharInputAdapterDecorator(ISampleClass decoratedClass)
{
this.decoratedClass = decoratedClass;
this.decoratedClass.OutputAvailable += (output) => {
this.OutputAvailable(output);
};
}
public void TakeInput(byte input)
{
this.decoratedClass.TakeInput(input);
}
public void TakeInput(char input)
{
switch (input)
{
case 'a':
this.TakeInput(27);
break;
case 'b':
// You get the idea...
}
}
}
// Now, I want to use the base class and get the benefit of both decorators:
ISampleClass smpl = new BaseSampleClass();
smpl = new SampleClassInputCacheDecorator(smpl);
smpl = new SampleClassCharInputAdapterDecorator(smpl);
// Dang, the input gets cached, but I can't access the InputHistory property.
Decorator is about altering the contracted behavior. You decorator adds completely new behavior, irrelevant in the context of the first one, and not being the part of the contract (the interface).
In fact SampleClassInputCacheDecorator is not a decorator - its actions are completely irrelevant from the ISampleClass point of view, as they don't influence TakeInput and OutputAvailable at all. It just depends on the ISampleClass chain, but does not "decorate" it. Proxy pattern seems more suitable here.

Passing continuous data between WinForms

I am making a personal WinForms app. In my scenario say I have a C# Form1. Form1 is constantly getting live Exchange data from the Internet. Now I click a button on Form1 and Form2 opens. Now I want some values from Form1 on Form2.
I have a timer on Form2 which can collect data from Form1 but how?
I had tried to use properties but not able to do that as it updates only once as when we initialize Form2.
Any solution?
Also, how can I pass a single instance of a class to both forms, if they are not being created at the same time?
I. Solution: Use a Common Data Source
Method 1: Data Source with Events
Well, if it were me, I would probably not be trying to directly get the data from Form1. Instead, I would set up a common datasource, and then you would even be able to eliminate the timer on Form2 and drive it by when the data comes in if you like. (Or you can leave it and just pull from the datasource as your desired intervals.)
It would be something like this:
Data Source class
public class ExchangeCommonDataSource
{
public event EventHandler NewDataReceived;
public void FireNewDataReceieved()
{
if (NewDataReceived != null)
NewDataReceived();
}
private string mySomeData1 = "";
public string SomeData1
{
get
{
return SomeData1;
}
set
{
SomeData1 = value;
FireNewDataReceieved();
}
}
// properties for any other data
}
Then, when you are opening your forms, you'll just create an instance of ExchangeCommonDataSource, and pass it to both of the forms. In the form that is receiving the data you'll want to create an event handler function, and wherever you pass it the data source, you'll hook up that event.
example: receiving class code
public void HandleDataReceived(object sender, EventArgs e)
{
// display the data
DoSomethingWith(mySource.SomeData1);
// etc...
}
private ExchangeCommonDataSource mySource;
public void SetDataSource(ExchangeCommonDataSource newSource)
{
mySource = newSource;
mySource.NewDataRecieved += new EventHandler(HandleDataReceived);
}
Then, in your first form, you just set the properties you want. You can actually have notifications that specified the actual data to load, either through separate event handlers, or by creating your own derived EventArgs and then using EventHandler<ExchangeCommonEventArgs> instead of a regular event handler.
example: main form data accessor
public void GetDataFromExchange()
{
mySource.SomeData1 = GetSomeData1FromExchange();
}
Also, this way you're not limited to having just those two forms communicate; if you decide to split it up with different forms, you could have each of them have a copy of the data source and each of them could handle the event or new events you define, and you're not tied to a model where you're expecting to communicate directly between each other. This would also allow, for instance, creating a separate class which writes some log data to disk, or whatever else you can imagine, without making significant changes to any of your existing stuff.
II. Extensibility for External Updates
The Dispatcher Base Class
So, what if you want to update to eventually send to another application or another machine even?
Well, this is actually very well accounted for since you've not got any dependencies on the forms left. So, say you wanted to support three methods: the initial, form to form method; sending via a named pipe to another app on the same machine; and TCP/IP to another machine entirely. All you would need to do is to define a class that acts as a dispatcher, hook it up as a receiver, and then you can hook up that object to take the events coming from the form and put the data wherever you want.
It should be fairly straightforward to define an abstract class or interface to do this, and then simply derive a class for any mode you want to support:
example: a notional abstract Dispatcher class
public class ExchangeDataDispatcher :
IDisposable
{
public ExchangeDataDispatcher(ExchangeCommonDataSource parDataSource)
{
myDataSource = parDataSource;
myDataSource.HandleDataReceived +=
new EventHandler(HandleDataReceived);
DispatcherInitialization();
}
private ExchangeCommonDataSource myDataSource;
private void HandleDataReceived(object sender, e EventArgs)
{
// here you could record statistics or whatever about the data
DispatcherHandleDataReceived(EventArgs);
}
protected abstract void DispatcherHandleDataReceived(e EventArgs);
protected abstract void DispatcherShutdown();
// significantly ripped from Microsoft's page on IDisposable
private bool disposed = false;
protected virtual void Dispose(bool disposing)
{
// Check to see if Dispose has already been called.
if(!this.disposed)
{
// If disposing equals true, dispose all managed
// and unmanaged resources.
if(disposing)
{
// call a function which can be overridden in derived
// classes
DispatcherShutdown();
}
// Note disposing has been done.
disposed = true;
}
}
}
see the Microsoft page on IDisposable for some great example code and more information on IDisposable...
Deriving Dispatchers for Other Communication Methods
There's no way to make the form itself derive from this class, but there's no real need since you can just hook up as before. But, as quick example (just notional, not actually implementing the protocols, and you really should really consider the best way to implement these types of things, but I wanted to give you a fairly comprehensive example of what it takes, it's not as simple as the really really naive versions tend to be. )
example: (very) notional Pipe-based Dispatcher
// add these to your using statments
using System.IO.Pipes;
using System.Threading;
// NOTE: take all the async stuff with a grain of salt; this should give you a
// basic idea but there's no way I've gotten it right without actually testing
// and debugging everything. See the link
// http://stackoverflow.com/questions/6710444/named-pipes-server-read-timeout
// for some information on why it has to be done this way: basically timeout
// is not supported for named pipe server streams.
public class ExchangeDataLocalMachineDispatcher :
ExchangeDataDispatcher
{
// see http://www.switchonthecode.com/tutorials/dotnet-35-adds-named-pipes-support
// for some info on named pipes in .NET
public ExchangeDataLocalMachineDispatcher(
ExchangeCommonDataSource parDataSource,
NamedPipeServerStream ServerPipe
) :
base(parDataSource)
{
myPipe = ServerPipe;
// do any extra initialization, etc. here, negotiation for instance
StartPipeThread();
}
private NamedPipeServerStream myPipe;
private ExchangeCommonDataSource myDataSource;
// assuming you have PipeMessage defined and that your handler
// fills them in.
private List<PipeMessage> myOutgoingMessages =
new List<PipeMessage>();
private Thread myPipeThread;
private bool EndPipeListener = false;
private AutoResetEvent myWaitEvent = null;
private AutoResetEvent myDataReadyToGoEvent = null;
// set this to something reasonable for the response timeout
private int WaitTimeout = 10000;
// example: at least every minute there should be data to send
private int WaitForDataToSendTimeout = 60000;
private void StartPipeThread()
{
IAsyncResult LastResult = null;
Action<IAsyncResult> WaitForResult =
(a) =>
{
LastResult = a;
myWaitEvent.Set();
}
myPipeThread = new System.Threading.ThreadStart(
() =>
{
try
{
myWaitEvent = new AutoResetEvent(false);
myPipe.BeginWaitForConnection(
WaitForResult, null
);
bool TimedOut = !myWaitEvent.WaitOne(WaitTimeout);
if (TimedOut || !LastResult.IsCompleted)
throw new Exception("Error: pipe operation error.");
while (!EndPipeListener)
{
byte[] Response = myPipe.BeginRead(
WaitForResult, null
);
myWaitEvent.WaitOne(WaitTimeout);
if (TimedOut || !LastResult.IsCompleted)
throw new Exception("Error: pipe operation error.");
// another assumed function to handle ACKs and such
HandleResponse(Response);
myWaitEvent.Set();
// now wait for data and send
bool TimedOut =
myDataReadyToGoEvent.WaitOne(WaitForDataToSendTimeout);
if (TimedOut || !LastResult.IsCompleted)
throw new Exception("Error: no data to send.");
// an assumed function that will pull the messages out of
// the outgoing message list and send them via the pipe
SendOutgoingMessages();
myDataReadyToGoEvent.Set();
}
myWaitEvent.Set();
}
finally
{
// here you can clean up any resources, for instance you need
// to dispose the wait events, you can leave the pipe for the
// DispatcherShutdown method to fire in case something else
// wants to handle the error and try again... this is all
// fairly naive and should be thought through but I wanted
// to give you some tools you can use.
// can't remember if you're supposed to use .Close
// .Dispose or both off the top of my head; I think it's
// one or the other.
myWaitEvent.Dispose();
myDataReady.Dispose();
myWaitEvent = null;
myDataReady = null;
}
}
);
}
protected PipeMessage[] ConstructEventMessage(e EventArgs)
{
// actually we're not using the event args here but I left it
// as a placeholder for if were using the derived ones.
return
PipeMessage.CreateMessagesFromData(
myDataSource.GetMessageData()
);
}
protected override void DispatcherHandleDataReceived(e EventArgs)
{
// create a packet to send out; assuming that the
// ConstructEventMessage method is defined
myOutgoingMessages.Add(ConstructEventMessage(e));
}
protected override void DispatcherShutdown()
{
// this is called from the base class in the Dispose() method
// you can destroy any remaining resources here
if (myWaitEvent != null)
{
myWaitEvent.Dispose();
}
// etc. and
myPipe.Dispose();
}
// you could theoretically override this method too: if you do, be
// sure to call base.Dispose(disposing) so that the base class can
// clean up if resources are there to be disposed.
// protected virtual void Dispose(bool disposing)
// {
// // do stuff
// base.Dispose(disposing);
// }
}
Phew. Note that I'm very unhappy currently with the length of the StartPipeThread function, and I would definitely be refactoring that.
So, you could also implement this for TCP/IP sockets, or whatever protocol you can imagine, and it's all handled without having to continually modify the classes from the first section.
My apologies for the quality of any of the code there; I am open to suggestion/correction/flaming about it, and I'll do my best to make corrections if you just let me know. :P
III. Putting the Data Where it's Needed
After you have this set up, you'll need to pass the same data to whatever forms are using it. If you're not creating both your forms at the same time, then you'll need some way to get each destination a reference to the same data source. (Note: the numbering of the options is in no way intended to imply these are your only choices!)
Here are a few options for doing so:
Option 1: via Property on your main Form
This method is appropriate if your main form is responsible for creating each of the child forms, for instance, through menu items. You simply create a member variable to hold the data, and wherever you create the data, store a reference to it in that member. If you have multiple instances of the source, you can store them e.g. in a dictionary that allows you to look up the one you need.
example: code for main Form
private ExchangeCommonDataSource myData { get; set; }
// you can also store in something that lets you identify multiple
// possible data sources; in this case, you could use, say, email address
// as a lookup: myData["mickey#example.com"];
//private Dictionary<string, ExchangeCommonDataSource> myData =
// new Dictionary<string, ExchangeCommonDataSource>();
public frmMyMainForm()
{
InitializeComponent();
// ... other initialization for the main form ...
// create the data here and save it in a private member on your
// form for later; this doesn't have to be in the constructor,
// just make sure you save a reference to the source when you
// do create your first form that uses the source.
myData = new ExchangeCommonDataSource();
}
// then, in the methods that actually create your form
// e.g. if creating from a menu item, the handlers
public void FirstFormCreatorMethod()
{
frmFirstForm = new frmFirstForm(myData);
frmFirstForm.MdiParent = this;
frmFirstForm.Show();
}
public void SecondFormCreatorMethod()
{
frmSecondForm = new frmSecondForm(myData);
frmSecondForm.MdiParent = this;
frmSecondForm.Show();
}
Option II: static Properties on your Data Source
This option can be used if the forms are being created externally from the main form, in which case you will not have access to its methods. The idea behind this method is that you want an easy way to find whatever item you need, independent of the main form itself, and by providing a static method, additional data consumers can find the sources on their own using properties accessible with access only to the class declaration and then some sort of key if there can be multiple sources.
example: ExchangeCommonDataSource.cs
// a dummy source class; this is just the parts that were relevant
// to this particular discussion.
public partial class ExchangeCommonDataSource
{
public string Username { get; set; }
public string OptionalString { get; set; }
public int MailboxNumber { get; set; }
public Guid SourceGuid { get; set; }
public long BigNumber { get; set; }
// these static members provide the functionality necessary to look
// retrieve an existing source just through the class interface
// this holds the lookup of Guid -> Source for later retreival
static Dictionary<Guid, ExchangeCommonDataSource> allSources =
new Dictionary<Guid,ExchangeCommonDataSource>();
// this factory method looks up whether the source with the passed
// Guid already exists; if it does, it returns that, otherwise it
// creates the data source and adds it to the lookup table
public static ExchangeCommonDataSource GetConnection(
Guid parSourceGuid, string parUsername, long parBigNumber
)
{
// there are many issues involved with thread safety, I do not
// guarantee that I got it right here, it's to show the idea. :)
// here I'm just providing some thread safety; by placing a lock
// around the sources to prevent two separate calls to a factory
// method from each creating a source with the same Guid.
lock (allSources)
{
ExchangeCommonDataSource RetVal;
allSources.TryGetValue(parSourceGuid, out RetVal);
if (RetVal == null)
{
// using member initializer, you can do this to limit the
// number of constructors; here we only need the one
RetVal = new ExchangeCommonDataSource(parSourceGuid) {
Username = parUsername, BigNumber = parBigNumber
};
allSources.Add(parSourceGuid, RetVal);
}
return RetVal;
}
}
// this function is actually extraneous since the GetConnection
// method will either create a new or return an existing source.
// if you had need to throw an exception if GetConnection was
// called on for existing source, you could use this to retrieve
public static
ExchangeCommonDataSource LookupDatasource(Guid parSourceGuid)
{
// again locking the sources lookup for thread-safety. the
// rules: 1. don't provide external access to allSources
// 2. everywhere you use allSources in the class,
// place a lock(allsources { } block around it
lock (allSources)
{
ExchangeCommonDataSource RetVal;
allSources.TryGetValue(parSourceGuid, out RetVal);
return RetVal;
}
}
// private constructor; it is private so we can rely on the
// fact that we only provide factory method(s) that insert the
// new items into the main dictionary
private ExchangeCommonDataSource(Guid SourceGuid)
{
// if you didn't want to use a factory, you could always do
// something like the following without it; note you will
// have to throw an error with this implementation because
// there's no way to recover.
//lock (allSources)
//{
// ExchangeCommonDataSource Existing;
// ExchangeCommonDataSource.allSources.
// TryGetValue(parSourceGuid, out Existing);
// if (Existing != null)
// throw new Exception("Requested duplicate source!");
//}
// ... initialize ...
}
}
now to access, the client just needs to have some sort of key to access the data:
example: frmClientClass.cs
public partial class frmClientClass
{
ExchangeCommonDataSource myDataSource = null;
public void InitializeSource(Guid parSourceGuid)
{
myDataSource = ExchangeCommonDataSource.GetConnection(parSourceGuid);
}
}
I find this a generally more compelling solution that Option 1, simply because anything that has access to the class and an ID can get the data source, and because it's fairly easy to implement, and it gives automatic support for doing multiple instances of your data source class.
It has fairly low overhead, and since getting a data source is, in most cases, something that is not going to be done in tight loops (and if it were, you would have local copies, not looking them up from a dictionary every time) any small performance loss should be worth the ease of use. And, best of all, even if you start with one data source, you can easily extend your application to more without having to rewrite any code or go to any further effort.
For instance, a very quick way to use this assuming you only have one data source would be just to use a known value for your Dictionary key, and then you just can hard code that in your second for for now. So, for the example, you could just have the empty GUID as your key, and use that for both your forms. i.e. the Main Form or your first data form would call the create method with Guid.Empty to create the data initially, and then you can just use that to access it when the time comes to open your second form.
Option 3: The 'Singleton' Pattern Class
Okay, I'm not going to spend much time or write code for this one, but I would be remiss if I didn't mention it. It's very similar to option 2, except, instead of having a static Dictionary to look up multiple data sources, you create a class that has one instance of the class stored in a static property, and you prevent (via exception) any attempts to create more classes. Then, you set all constructors to private, have them throw exceptions if the static variable already contains an object, and you create a getInstance() method which returns the single instance of the class, creating it if it's null.
Now, there are some little thread-safety trickiness issues with this that you will need to understand to write a traditional singleton, so be sure to understand those (there are questions on StackOverflow dealing with the issue). If you don't need any particular knowledge to construct the instance of the class, you can avoid the issues by simply initializing the variable where you declare it e.g. static MyClass theInstance = new MyClass();, and I highly recommend doing that if you do ever use one.
I have used Singletons in the (fairly distant) past, and it's not that they don't occasionally have their uses, especially in embedded systems. But, this is not an embedded system, and almost every time I used a Singleton in a GUI application, I regretted doing it because I ended up eventually re-writing it into something that would allow multiple instances. If you really just need one copy, all you have to do is put a member variable in the class that uses it, say, your main form, and make sure that you don't ever create but one. Doing this, you could even use the pattern by setting a static flag in the class that you can trigger an exception on; set it to true when you first create the object, and then if that's true you can throw your exception.
Anyway, my personal first rule for when to write a singleton is: don't do it unless you are certain you will never need more than one. If it passes that one, then the second rule is: you are wrong, there is a way it could happen, so just write it as a normal class and handle the singleton-ness of it in some other way. :) Seriously though, the real rule is, just don't do it unless you have get some a very solid reason or a significant benefit from doing it.
Oh, and to reiterate: it's very possible to accomplish the pattern of singleton, without writing the canonical singleton class. The pattern is fine, just do it in a way that when that need for a second instance of that class comes along, there is a very low cost to eliminate the pattern.
Option 4: A Separate Class
Option 4 is very similar to Option 2, but implemented in a second class. (In fact, if you ever think you might have multiple sources of data, it would be worthwhile to just start here, although it's a little more time to set up initially.) Instead of having your static items as members of that class, implement another class that has something like them and provides access. This is a way to decouple the class itself from the creating of it. For example, if you were writing a library, and you wanted to provide several different types of data source, you could implement a base class and then derive your other objects from the base class, and then provide creation mechanisms via a class that gives factory methods to create the different kinds.
In a situation like this you very well may not even want whatever is using your data source to have to know anything about the implementation of the data source classes at all, and only go through the base interface, and this provides an easy way to do that. If you had to write it all as base class static members, then you would be forcing a rewrite of the base every time you derived a new class, and it would also be forcing the base to know something about the derived classes, each of which is, in general, something to avoid. In other words, it's not that it's never useful, but don't do it without very good reason, and don't do it without understanding the implications.
example: code for external class
InfostoreBase.cs
// our data source base class; could do interface instead like:
// public interface IInfostoreBase
public abstract class InfostoreBase
{
public abstract int Information { get; set; }
public abstract string NameOfItem { get; set; }
public abstract decimal Cost { get; set; }
// ... etc ...
}
InfostoreEnterprise.cs
public class InfostoreHomeEdition :
InfostoreBase
{
public override int Information { get { /* ... */ } set { /* ... */ }}
public override string NameOfItem { get { /* ... */ } set { /* ... */ }}
public override decimal Cost { get { /* ... */ } set { /* ... */ }}
public void SetFeatures(string parSomething) { /* ... */ }
}
InfostoreHomeEdition.cs
public class InfostoreEnterpriseEdition :
InfostoreBase
{
public override int Information { get { /* ... */ } set { /* ... */ }}
public override string NameOfItem{ get { /* ... */ } set { /* ... */ }}
public override decimal Cost { get { /* ... */ } set { /* ... */ }}
public void SetBaseDiscount(decimal parSomethingElse) { /* ... */ }
}
InfostoreProvider.cs
public class InfostoreProvider
{
static Dictionary<Guid, InfostoreBase> allSources =
new Dictionary<Guid,InfostoreBase>();
public static InfostoreBase
GetHomeConnection(Guid CustomerKey, string HomeFeatures)
{
lock (allSources)
{
InfostoreBase RetVal;
if (!ValidHomeKey(CustomerKey))
throw new
InvalidKeyException("not valid for Home Edition");
allSources.TryGetValue(CustomerKey, out RetVal);
if (RetVal == null)
{
RetVal = new InfostoreHomeEdition();
allSources.Add(CustomerKey, RetVal);
}
var ActualVersion = (InfostoreHomeEdition) RetVal;
RetVal.SetFeatures(HomeFeatures);
return RetVal;
}
}
public static InfostoreBase
GetEnterpriseConnection(Guid CustomerKey, decimal BaseDiscount)
{
lock (allSources)
{
InfostoreBase RetVal;
if (!ValidEnterpriseKey(CustomerKey))
throw new
InvalidKeyException("not valid for Enterprise Edition");
allSources.TryGetValue(CustomerKey, out RetVal);
if (RetVal == null)
{
RetVal = new InfostoreHomeEdition();
allSources.Add(CustomerKey, RetVal);
}
var ActualVersion = (InfostoreEnterpriseEdition) RetVal;
RetVal.SetBaseDiscount(CostBase);
return RetVal;
}
}
}
code in client class
private InfostoreBase myConnectionSource;
private void Initialize()
{
// ...
myConnectionSource =
InfostoreProvider.GetConnection(
myKey, isEnterprise, myData
);
//...
}
Closing
I think that covers a very good range of possible solutions; none of them is particularly hard to implement, and each has its own benefits and disadvantages. In general I would go for Option 2 or Option 4, but [broken record] it always depends on your exact situation. I think it would be fairly easy to use extend these to handle lots of different situations. And of course if there are any problems, just let me know.
Another possible way to handle this would be to create some interfaces to represent the role of data provider and data receiver, and then you would implement those interfaces on your form. It would be very similar to doing it with a common data source, but instead of running things through an object, you would implement the interfaces and the data can go directly where it is needed. It may be a bit more efficient that doing it through a DataSource, although it's hard to say without knowing all the specifics, but if you are really transferring loads of data putting it through a separate datasource could cost you some efficiency, especially if you never have a need for all the data in one spot.
In the example code here I'm showing what it would look like if you implemented your own event args for different types of data, this also could be used in a common data source for the events if you wanted to be able to have a little more granularity over what got sent when. (Please keep in mind I've typed this all in on the webpage without trying to compile it; this is supposed to give you the idea of how to do it, but its possible (I would estimate 100% change) that I didn't get everything in perfectly. :D)
public class FirstDataKindEventArgs : EventArgs
{
public FirstDataKindEventArgs(int parID, string parName, string parOtherInfo)
{
Id = parId;
Name = parName;
OtherInfo = parOtherInfo;
}
public int ID { get; set; }
public string Name { get; set; }
public string OtherInfo { get; set; }
}
// plus other event arg definitions
public interface IExchangeDataProvider
{
event EventHandler<FirstDataKindEventArgs> FirstDataKindReceived;
event EventHandler<SecondDataKindEventArgs> SecondDataKindReceived;
event EventHandler<ThirdDataKindEventArgs> ThirdDataKindReceived;
}
public interface IExchangeDataReceiver
{
void ConnectDataProvider(IExchangeDataProvider Provider);
}
then in your data providing form you would implement the interface:
public partial class MyProvidingForm : System.Windows.Forms.Form, IExchangeDataProvider
{
// normal form stuff
// ...
#region IExchangeDataProvider
public event EventHandler<FirstDataKindEventArgs> FirstDataKindReceived;
public event EventHandler<SecondDataKindEventArgs> SecondDataKindReceived;
public event EventHandler<ThirdDataKindEventArgs> ThirdDataKindReceived;
public void FireDataReceived(EventArgs Data)
{
FirstDataKindEventArgs FirstKindData = Data as FirstDataKindEventArgs;
if (FirstDataKindEventArgs != null)
if (FirstDataKindReceived != null)
FirstDataKindReceived(FirstKindData);
//... etc.
}
public void GotSomeDataOfTheFirstKind(int TheID, string SomeName, string Other)
{
FirstDataKindEventArgs eArgs =
new FirstDataKindEventArgs(TheId, SomeName, Other);
FireDataReceived(eArgs);
}
and in your receiver form(s) or other classes you wish to receive data:
public partial class FirstDataKindReceivingForm :
System.Windows.Forms.Form,
IExchangeDataReceiver
{
// usual form stuff
// ...
private IExchangeDataProvider myDataProvider;
public void ConnectDataProvider(IExchangeDataProvider Provider)
{
myDataProvider = Provider;
myDataProvider.FirstDataKindReceived +=
new EventHandler<FirstDataKindEventArgs>(
HandleFirstKindOfDataReceived
);
}
private void HandleFirstKindOfDataRecieved (
object sender, FirstDataKindEventArgs
)
{
// do whatever with data
}
}
#endregion
}
and so forth.
edit Form2 's constructor, so that you can pass some values from Form1 while running a new Form2 with .Show or .ShowDialog
Form2 myForm = new Form2(value1, value2, value3 ...);
And on Form2.cs you shall convert (or add a new one) public Form2() to public Form2(var value1, var value 2...)
If you have to send to Form2 continuously data, you may use a shared memory or shared data file.
The answer in the db forum by Mahrous seems to be the simplest http://www.daniweb.com/software-development/csharp/threads/126879/617436#post617436
Some of the other solutions are also valid and may be appropriate depending on the design of the applicaiton.

Categories