Class programming approach for child/parent relationship - c#

I'm developing a program that scrapes content from various online archives, but am new to OOP. The way I believe would work best would be to have a parent class that specifies the shared variables and methods, then a child class for each archive which then contains the specific methods for grabbing info from that particular site, such as GrabStoryVariables() existing in each child class to accommodate the individual needs of that archive. The program takes a URL in a textbox, and then from there it will determine using the URL which child class to instantiate.
The problem I'm having is figuring out how to create the child class object and make it accessible to the entire program. For example, to create an instance of FanFictionAuthors : FanBook:
private void btnGetInfo(object sender, EventArgs e)
{
CreateBook();
}
private void CreateBook()
{
if (addressBar.Text.Contains("fanficauthors.net"))
{
FanFictionAuthors myBook = new FanFictionAuthors();
}
return;
}
The scope of myBook is just the CreateBook() function, so this approach won't do the trick. Any suggestions on the best way to handle this issue? I'm using this as an approach to better learn programming, so the "correct" way is what I'm trying to figure out, whatever that is.
Edit: The specific function of the program is to take a provided URL for an online story from fanfiction.net, fictionpress.com, or one of any number of other online story archives. There are a set of shared attributes each story will have, such as title, number of chapters, length in words, chapter titles, and the actual content of the story. The program compiles all of this to create a single html document (later to be expanded to allow for different ebook formats) rather than a bunch of small individual chapter files.
With that in mind, the only parts that should differ between each archive are the methods for grabbing the variables from the particular archive and how to iterate between the chapters based on the archive's function for that.
Currently what I'm doing is just creating a myBook object immediately upon launching the main form, then creating a different method name for the functions that grab the variables and do the iteration. As I add more archives, however, this becomes more complicated. What I originally wanted to do was to just cast the myBook to the individual archive types (FanFictionAuthors in this case) to grab the ability to use their specific functions. Looking online, it appears casting from parent to child isn't easy nor recommended, so I'm not sure how else to approach this.
Here's the GitHub link for the project. This version is slightly out of date, but lets you see how I'm currently approaching this: https://github.com/benroth/fBook

Create a super class where you common attributes and methods in there:
public class FanBook
{
// use a common constructor
public FanBook(string url)
{
grabHtml(url);
// ...
}
protected string grabHtml(string address) { // SNIP }
protected void CreateStoryHeader() { // SNIP }
// other common methods which are the same for every subclass (maybe BuildToc, GetStory, etc.)
// maybe if you want some easy access to attributes, you could add a dictionary
public void Dictionary<string, string> Attributes;
// Then use abstract methods to define methods that are different for subclasses
protected abstract void GrabStoryVariables();
protected abstract void GenerateStoryInfo();
}
Then create a subclass that derives from Book:
public class FFNETBook : FanBook {
// FFNETBook constructor to call contructor from FanBook too
public FFNETBook(string url) : FanBook(url) {
// specific initializations for FFNET
}
public override void GrabStoryVariables() { // special implementation for FFNET here }
public override void GenerateStoryInfo() { // special implementation for FFNET here }
}
I know OOP is hard to grasp when you don't have much experience in it. So feel free to ask questions.
If you do it right, then you would never need to cast into subclasses.
To answer the question in the comment:
You could make a class variable in the form1.cs file:
private FanBook currentBook;
private void CreateBook()
{
currentBook = new FFNETFanBook("http://...");
}
private void AnotherMethod() {
if ( currentBook != null ) {
currentBook.GrabStoryVariables();
} else {
throw new Exception("Book not initialized yet.");
}
}

Implement an interface named IAuthors and define the Method you want
Interface IAuthors
{
//method
void authorMethod();
}
Implement the interfaces across your classes
Public Class FanFictionAuthors:IAuthors
{
public void authorMethod()
{
//fanfiction specific action
}
}
Public class SciFiAuthors:IAuthors
{
public void authorMethod()
{
//scifiauthor specific action
}
}
Now make the following changes in your existing code
private void btnGetInfo(object sender, EventArgs e)
{
IAuthors auth=CreateBook();//Use a Interface ref
auth.authorMethod();//Runtime will decide which authorMethod to call depending
//on the object returned.
}
//Note that i am returning the Interface type instead of the void
private IAuthors CreateBook()
{
if (addressBar.Text.Contains("fanficauthors.net"))
{
return new FanFictionAuthors();//Return your object
}elseif(addressBar.Text.Contains("scificauthors.net"))
{
return new SciFiAuthors();//Return your object
}
}

You could create a list in the parent and add childs to that list. Then you can akso walk that list to see if childs are finished and such.
ChildList.Add(new fan....)

Related

Marten: Define schema stuff (like indexes etc) not in the constructor/factory call to create the DocumentStore

I just started testing Marten (2.9), and so far I am loving it. However, I am not sure I am following the DocumentStore.For method. For example, in my "dbhandler" for Marten, I can write:
public MartenDbHandler()
{
store = DocumentStore.For(_ =>
{
_.AutoCreateSchemaObjects = AutoCreate.CreateOrUpdate;
_.Connection("host=localhost;database=marten;password=root;username=postgres");
_.Schema.For<Customer>().Index(x => x.PopulationRegistryNumber);
});
}
but naturally, I do not want to have all that schema code when I initialize the database and supply the connection string.
So I thought, maybe I can pass on the store variable, and do the same, but then the For thing doesn't exist:
... and I haven't really found a way to set the Schema in any other way.
What I really want to do is to have an Interface, that is dynamically loaded and executed (via Reflection) when I start my application, that handles those things, like an IMartenMetaData that looks something like:
public interface IMartenMetaData
{
SetMetaData(DocumentStore store);
}
and then implement the schema things in that/those classes, but that doesn't work because I can't use the DocumentStore to set the meta.
Keep it simple. The document store is supposed to have a single instance in your app and you define the schema properties during construction. No need to abstract the store.
One way is you can create your own implementation of DocumentStore. You can refer to the test document store classes in the source code.
Update:
You can find the sample here https://github.com/JasperFx/marten/blob/master/src/Marten.Testing/TestingDocumentStore.cs
I managed to do a much nice approach to keep it more dynamic and not all in the construction of DocumentStore.
Please see code below. The idea is straightforward:
Create the StoreOptions separately
Before creation of the DocumentStore, run method that via Reflection finds all classes of a certain Type that will add table meta data
Create the DocumentStore
public MartenDbHandler()
{
StoreOptions so = new StoreOptions();
so.Connection("host=localhost;database=marten;password=root;username=postgres");
so.AutoCreateSchemaObjects = AutoCreate.CreateOrUpdate;
SetTableMeta(so);
store = new DocumentStore(so);
}
private void SetTableMeta(StoreOptions storeOptions)
{
// We get the current assembly through the current class
var currentAssembly = Assembly.GetExecutingAssembly();
// we filter the defined classes according to the interfaces they implement
var stuff = currentAssembly.DefinedTypes.Where(type => type.IsSubclassOf(typeof(MartenTableMetaDataBase))).ToList();
foreach (Type type in stuff)
{
IMartenTableMetaData temp = (IMartenTableMetaData)Activator.CreateInstance(type);
temp.SetTableMetaData(storeOptions);
}
OnLogEvent?.Invoke(this, $"{stuff.Count} table meta data initialized");
}
The IMartenTableMetaData is a base class for the IMartenTableMetaData interface. In the example below, the base class isn't used, but I normally find it good to have a base class (I use a similar approach to another ORM, where I actually use the base class). But, the base class can of course be removed if you have no use for it.
internal abstract class MartenTableMetaDataBase : IMartenTableMetaData
{
public void SetTableMetaData(StoreOptions storeOptions)
{
SetSpecificTableMetaData(storeOptions);
}
protected abstract void SetSpecificTableMetaData(StoreOptions storeOptions);
}
and the interface:
public interface IMartenTableMetaData
{
void SetTableMetaData(StoreOptions storeOptions);
}
So, I can now create a class for each Type I want to add meta data too, like this:
internal class MartenTableMetaDataCustomer : MartenTableMetaDataBase
{
protected override void SetSpecificTableMetaData(StoreOptions storeOptions)
{
storeOptions.Schema.For<Customer>().Index(x => x.Muni);
}
}
or
internal class MartenTableMetaDataDriver : MartenTableMetaDataBase
{
protected override void SetSpecificTableMetaData(StoreOptions storeOptions)
{
storeOptions.Schema.For<Driver>().Index(x => x.Username);
}
}
etc.
This will keep the Marten DB handler clean and meta data separated into specific classes for readability, clarity and all that stuff =)

First experience of using interfaces in C#?

I have an interface:
interface ISqlite
{
void insert();
void update();
void delete();
void select();
}
And custom service class:
class SqliteService
{
public SQLiteDatabase driver;
public SqliteService() {
SqliteConnection(new SQLiteDatabase());
}
public void SqliteConnection(SQLiteDatabase driver)
{
this.driver = driver;
}
public void select(ISqlite select) {
select.select();
}
public void insert(ISqlite insert) {
insert.insert();
}
public void delete(ISqlite delete)
{
delete.delete();
}
}
And last class Pacients that realizes ISqlite interface:
class Pacients: ISqlite
{
public List<ClientJson> pacients;
public Pacients() {
this.pacients = new List<ClientJson>();
}
public void add(ClientJson data) {
this.pacients.Add(data);
}
public void insert()
{
throw new NotImplementedException();
}
/* Others methos from interface */
}
I try to use my code like as:
/* Create instance of service class */
SqliteService serviceSqlite = new SqliteService();
/* Create instance of class */
Pacients pacient = new Pacients();
pacient.add(client);
serviceSqlite.insert(pacient);
As you can see above I send object pacient that realizes interface ISqlite to service. It means that will be called method insert from object pacient.
Problem is that I dont understand how to add data in this method using external class: SQLiteDatabase()? How to get access to this.driver in service class from object pacient?
Edit 1
I think I must move instance of connection new SQLiteDatabase() to db inside Pacients class is not it?
Generally speaking, I would favor a solution where the data objects themselves don't know anything about how they're stored, i.e. they have no knowledge of the class that communicates with the database. Many ORMs do just that.
Of course it might not be easy depending on the specifics of your situation... Try to examine what your methods on each object actually need; generally speaking they need the values of properties, and what column each property corresponds to, right? So any external class can do this if it knows these bits of information. You can specify the name of the column with a custom attribute on each property (and if the attribute isn't there, the column must have the same name as the property).
And again, this is the most basic thing that ORMs (Object Relational Mappers) do, and in addition they also manage more complicated things like relationships between objects/tables. I'm sure there are many ORMs that work with SqlLite. If you're OK with taking the time to learn the specifics of an ORM, that's what I would recommend using - although they're not silver bullets and will never satisfy all possible requirements, they are in my opinion perfect for automating the most common day to day things.
More to the point of the question, you can of course make it work like that if you pass the SQLiteDatabase object to the methods, or keep it in a private field and require it in the constructor or otherwise make sure that it's available when you need it; there's no other simple solution I can think of. And like you pointed out, it implies a certain degree of coupling.
You can change the signature of interface's methods to pass an SQLiteDatabase object.
interface ISqlite
{
void insert(SQLiteDatabase driver);
void update(SQLiteDatabase driver);
void delete(SQLiteDatabase driver);
void select(SQLiteDatabase driver);
}
Example call from the service:
public void insert(ISqlite insert)
{
insert.insert(driver);
}
I think you can figure out the rest by yourself.

How to check the type of a list if inheritance is used

I'm currently working on a C# program that creates a List, of object Task, the object Task is a base class and many other inherit from it. What I want to is compare the type of one of the object within said list to see which form should be opened in order to edit it.
This is the code I have already created.
private void itemEdit_Click(object sender, EventArgs e)
{
int edi = taskNameBox.SelectedIndex;
Task checkTask = todoList.ElementAt(edi);
if(checkTask.GetType is Note)
{
noteBuilder editNote = new noteBuilder(todoList);
editNote.Show();
}
else if(checkTask.GetType is extendedTask)
{
extendedTaskBuilder editTask = new extendedTaskBuilder(todoList);
editTask.Show();
}
else if(checkTask.GetType is Reminder)
{
reminderBuilder editReminder = new reminderBuilder(todoList);
editReminder.Show();
}
else if (checkTask.GetType is Appointment)
{
appointmentBuilder editAppointment = new appointmentBuilder(todoList);
editAppointment.Show();
}
}
On a secondary note would it be easier if instead of passing the list between the forms and generating a new object of the form that display information that I instead pass a single object between forms and just update the form every time a new element is added to the list.
Many thanks
Have you tried checking like this:
if (checkTask is Note)
{
}
...
Have you considered creating a base class for all types you are now switching between and call a virtual (abstract) method?
Put all code now in the if in the overridden abstract method.
Advantages:
- The intelligence of the switch is within the classes where it belongs.
- When a new type is added you get a compiler error to also add this feature to the new type.
I suggest that instead of doing that series of ‘if’ clauses, you use inheritance to achieve what ou need. First you create a virtual method in your base class. A virtual method means it won't have any implementation in the base class, only the declaration:
public class Task
{
(...)
public virtual void ShowEditForm(IList todoList);
(...)
}
Then you create the child class methods (I'm assuming the todoList object is a IList, but just change it if it is not).
public class Note: Task
{
(...)
public override void ShowEditForm(IList todoList)
{
(new noteBuilder(taskToEdit)).Show();
}
(...)
}
public class Reminder: Task
{
(...)
public override void ShowEditForm(IList todoList)
{
(new reminderBuilder(taskToEdit)).Show();
}
(...)
}
I didn't write all the classes, but I think you've got the idea. To call the method, you just call the method from Task class, and the right method will be executed:
int edi = taskNameBox.SelectedIndex;
Task checkTask = todoList.ElementAt(edi);
checkTask.ShowEditForm(todoList);
This way, when you want to create new types of Task, you just have to create the child class, with the proper method, and the inheritance system will do the rest.
One more thing, the override keyword in the child method declaration is important, because it says to the compiler that this method should be called even if you call it from the BaseClass.
First, to your second note. What you are talking about doing is having a global object that all forms refer to in some parent. That can work, however you will need to make sure there is some mechanism in place that makes sure all of the forms are synchronized when one changes, and this can get messy and a bit of a mess to maintain. I am not necessarily advocating against it per say, but just adding words of caution when considering it :)
As to your posted code, it would probably be better to turn this into a Strategy Pattern approach, where all forms inherit from a base class/interface which has a Show method. Then all you need to do is call checkTask.Show(todoList);. If you do not want that coming from the Task, then you could have your forms all inherit from the above base and you could use a factory pattern that takes in the Task and list and returns the appropriate form on which you simply call form.Show();
Code like this is difficult to maintain, you are probably better off abstracting this out, like so (assuming Task is not the one included in .net):
public interface IBuilder
{
void Show();
}
public abstract class Task
{
// ...
public abstract IBuilder GetBuilder(TaskList todoList);
// ...
}
public class Note : Task
{
public override IBuilder GetBuilder(TaskList todoList)
{
return new noteBuilder(todoList);
}
// ...
}
// etc.
private void itemEdit_Click(object sender, EventArgs e)
{
int edi = taskNameBox.SelectedIndex;
Task checkTask = todoList.ElementAt(edi);
IBuilder builder = checkTask.GetBuilder(todoList);
builder.Show();
}
Alternately, you can use an injection pattern:
public abstract class Task
{
protected Task(Func<TaskList, IBuilder> builderStrategy)
{
_builderStrategy = builderStrategy;
}
public IBuilder GetBuilder(TaskList todoList))
{
return _builderStrategy(todolist);
}
}
public class Note : Task
{
public Note(Func<TaskList, IBuilder> builderStrategy) : base(builderStrategy) {}
}
// ...
note = new Note(x => return new noteBuilder(x));

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.

Is this the example of polymorphism?

I kinda know what polymorphism is but failed to understand it clearly. Also my code is following:
class Human
{
public virtual void CleanTheRoom()
{
}
}
class Woman:Human
{
public override void CleanTheRoom()
{
//women clean faster
}
}
class Man:Human
{
public override void CleanTheRoom()
{
//men clean slower, different code here
}
}
class Child:Human
{
public override void CleanTheRoom()
{
//empty ... children are lazy :)
}
}
Should I explain this is polymorhism because all derived classes from base class Human contain method CleanTheRoom but each of them it implements differently?
The benefit of polymorphism comes when you want to invoke the method on some type of Human, but you don't care which one specifically.
By having CleanTheRoom() defined at the base class level, Human, you can write shorter, cleaner code elsewhere in your application whenever you are working with an instance of Human, whether it be a Child or otherwise.
Polymorphism, for example, lets you avoid lengthy conditional statements where you explicitly check for each type of Human and call a different method:
Good:
private void SomeMethod(Human h)
{
//some logic
h.CleanTheRoom();
//more logic
}
Bad:
private void SomeMethod(Human h)
{
//some logic
if (h is Adult)
CleanTheRoom();
else if (h is Child)
GoofOff();
//some logic
}
What you have is a good example of inheritance. Polymorphism refers specifically to being able to refer to objects of different types by using a single type (the parent class or interface), something this type of inheritance makes possible. Like so:
List<Human> humans = new ArrayList<Human>();
humans.add(new Woman());
humans.add(new Woman());
humans.add(new Man());
humans.add(new Child());
humans.add(new Child());
foreach(Human hum in humans) {
hum.CleanTheRoom(); //I don't know the type of hum, but I don't care
}
Say I've been collecting instances of Human from various locations -- I don't know what type each one is. But I can still iterate over them and call CleanTheRoom(), because they share a parent class.
I'll add a real-world example. Say I have an Invoice class with various subclasses for different types of Invoices -- maybe there are different kinds of Invoices for service clients versus customers who make one-time purchases. Sometimes I care deeply about the differences, and I only deal with one type. But sometimes I want to loop through all of the invoices for this month and print them out. If the parent class has a print() method (which may well be implemented differently by different types) then I can do that.
Yes, that is correct. And you can call the method CleanTheRoom() without knowing which "kind" of human is it.
Here you have some basic examples.
I think you fail to see the benefit, that's the key you're missing to fully understand polymorphism. I will try to make an example:
Let's say you have a simple CRUD form. This is the code of the save button:
var Client = PopulateDTO(); //put all the values in the controls, to an object
if(Action==Actions.Create){
_repository.Create(Client);
}
else if(Action==Actions.Update){
_repository.Update(Client);
}
else if(Action==Actions.Delete){
_repository.Delete(Client);
}
this.Close();
This code works, but it's bad code, and difficult to read. Let's use polymorphism (and the strategy pattern):
public abstract class BaseStrategy{
abstract void Do(ClientDto Client);
}
public class CreateStrategy:BaseStrategy{
public override void Do(ClientDto Client){
_repo.Save(Client);
}
}
public class UpdateStrategy:BaseStrategy{
public override void Do(ClientDto Client){
_repo.Update(Client);
}
}
public class DeleteStrategy:BaseStrategy{
public override void Do(ClientDto Client){
_repo.Delete(Client);
}
}
So, we have an abstract class, and 3 implementations, each one doing something with the client object. Now, the code of the save button in the form will be:
BaseStrategy stg = GetCorrectStrategy();
var Client = PopulateDTO();
stg.Do(Client);
this.close;
And the method GetCorrectStrategy() will instantiate the correct Strategy implementation, depending if the user is creating, editing or deleting the client.
I hope this answer will help you. But if didn't help you, I suggest you read about strategy pattern, It's one of the best uses of polymorphism in my opinion
Since several people have already given fine examples of polymorphism, I'll offer a different perspective that really helped me to grok it.
In functional programming, functions are the first class concepts in contrast to OOP where objects are supreme.
Polymorphism is to OOP what pattern matching is to FP. Here is a function that uses pattern matching (using an ML style syntax).
let f x =
match x with
| T -> //do stuff with a T to return some value
| S -> //do stuff with an S to return some value
| U -> //do stuff with a U to return some value
| V -> //do stuff with a V to return some value
So when you use the function f, you can pass it an object of either type T, S, U, or V. In strongly typed FP languages like F#, the type of x is denoted T|S|U|V. Such types are commonly referred to as Sum types or Tagged Unions.
If we fix up your example to make Human an abstract class, then it will become clear that polymorphism in OOP just gives you a way of expressing a sum type.
Thus, CleanTheRoom is a function that takes a type Human. But Human is just the name for the type Man|Woman|Child which is a sum type. The big difference between languages like C# and functional languages like F# is that one treats objects as top level things while the other treats functions as top level things. Also, everything in OOP languages like C# must have names. In a functional language we could denote the type Man|Woman|Child without having to explicitly name it.
The key is not to think of the code as having different CleanTheRoom methods, but rather think of CleanTheRoom as one method that takes a type Man|Woman|Child (which is named Human). Polymorphism is just the implementation detail.
In summary, polymorphism (especially with abstract classes) basically just give you a way to name sum types and do pattern matching.
See:
http://en.wikipedia.org/wiki/Tagged_union
http://en.wikipedia.org/wiki/Algebraic_data_type
An example in C#:
This is my class file
class parent
{
public virtual string saySomething(string s)
{
return s+":Parent";
}
}
class man : parent
{
public override string saySomething(string s)
{
return s+":Man";
}
}
class woman : parent
{
public override string saySomething(string s)
{
return s+":Woman";
}
}
class child : parent
{
public override string saySomething(string s)
{
return s+":Child";
}
}
Create Four Buttons and a label.
Here is the implementation on a simple form1
private void Form1_Load(object sender, EventArgs e)
{
p1= new parent();
}
private void button1_Click(object sender, EventArgs e)
{
label1.Text = p1.saySomething("I am parent!");
}
private void button2_Click(object sender, EventArgs e)
{
p1 = new man();
label1.Text = p1.saySomething("I am man!");
}
private void button3_Click(object sender, EventArgs e)
{
p1 = new woman();
label1.Text = p1.saySomething("I am woman!");
}
private void button4_Click(object sender, EventArgs e)
{
p1 = new child();
label1.Text = p1.saySomething("I am child!");
}
Is it run-time polymorphism?
P1 is an object. Depending upon the situation (Context), a button click, it is executing different piece of code. So, p1 is behaving differently depending upon the click event.
class Program
{
static void Main(string[] args)
{
List<ICleanTheRoom> cleanerList = new List<ICleanTheRoom>
{
new Child(),
new Woman(),
new Man()
};
foreach (var cleaner in cleanerList)
{
cleaner.CleanTheRoom();
}
}
}
internal interface ICleanTheRoom
{
void CleanTheRoom();
}
// No need for super type
//class Human : ICleanTheRoom
//{
// public virtual void CleanTheRoom()
// {
// }
//}
internal class Woman : ICleanTheRoom
{
public void CleanTheRoom()
{
throw new NotImplementedException();
}
}
class Man: ICleanTheRoom
{
public void CleanTheRoom()
{
throw new NotImplementedException();
}
}
class Child: ICleanTheRoom
{
public void CleanTheRoom()
{
throw new NotImplementedException();
}
}
Is it a new object created each time at runtime, clearly inheriting but no polymorphing.

Categories