Reputation: 595
STARTING QUESTION
My general understanding of Interfaces is fine, I’ve read hundreds of examples and different articles on this subject but I’m still on a hold, because all this reading still hasn't given me an answer to where to use this tool in my own project.
I'll try to come with a concrete example from my project on where I probably would have benefits from using Interfaces and hopefully someone could give me a concrete answer on how I should implement it.
My purpose with this project was to draw an image in A4 size and preview it in a PictureBox (resized) and then have a GUI to create and move a barcode (with a caption text underneath) on this image in the PictureBox.
Now I want to be able to draw another text object with same functionalities to move it around and show on the preview. But this will be a normal text and therefore it would have a different font and no caption. This could easily be done with a collection and a loop when drawing.
But what if I want to add more objects to this image, wouldn't it be a lot easier to maintain and extent, if I used Interfaces? I would also like to elaborate my programming, by learning how to use something a little bit more complex.
CURRENT APPROACH TO A SOLUTION
My main Interface
public interface IElementCreator
{
int posX { get; set; }
int posY { get; set; }
StringFormat format { get; set; }
string value { get; set; }
Font font { get; set; }
bool caption { get; set; }
Font captionFont { get; set; }
}
My main class for creating an element
public class ElementBase : IElementCreator, IImageUpdater
{
#region IElementCreator Variables
private int _posX;
private int _posY;
private StringFormat _format;
private string _value;
private Font _font;
private bool _caption;
private Font _captionFont;
#endregion
#region IElementCreator Members
public int posX
{
get { return _posX; }
set { _posX = value; }
}
public int posY
{
get { return _posY; }
set { _posY = value; }
}
public StringFormat format
{
get { return _format; }
set { _format = value; }
}
public string value
{
get { return _value; }
set { _value = value; }
}
public Font font
{
get { return _font; }
set { _font = value; }
}
public bool caption
{
get { return _caption; }
set { _caption = value; }
}
public Font captionFont
{
get { return _captionFont; }
set { _captionFont = value; }
}
#endregion
#region Constructor
public ElementBase(int posX, int posY, StringFormat format, string value, Font font, bool caption, Font captionFont)
{
this.posX = posX;
this.posY = posY;
this.format = format;
this.value = value;
this.font = font;
this.caption = caption;
this.captionFont = captionFont;
}
#endregion
public Image updatePreview(IElementCreator element, Image img)
{
}
}
Interface to update the preview image
public interface IImageUpdater
{
Image updatePreview(IElementCreator element, Image img);
}
I've not been able to test this yet, I've made the code and I'll start testing later.
What I'm trying to achieve, is to have an interface to handle the creation of a basic text element. With this it should be possible to extent with new classes to handle text elements with different settings.
This is just a starting point and I know some code are missing for everything to make sence, but I just want to share and make sure that i'm not completely of track.
Upvotes: 2
Views: 877
Reputation: 2075
What you could do if have a class which is responsible for creating image
public class ImageCreator : IImageCreator
{
public Image CreatePreviewImg(string value, int fontSize, int x, int y)
{
//Your code goes here...
}
}
then whenever you want to generate an image you could create an instance of image creator
IImageCreator imageCreator = new ImageCreator;
var preview = imageCreator.CreatePreviewImg(...);
thanks to this approach you could have multiple image creators implementing IImageCreator interface and your manager would decide which one to use.
Hope that give you an idea how to use interface in your project.
UPDATE *LATEST UPDATE AS OF 09/02/2012*
here's how the interface should look like
public interface IImageCreator
{
public Image CreatePreviewImg(string value, int fontSize, int x, int y);
}
as soon as you implement interface to your class, you will have to write code for that method. so your class would look like :
this is your image item - an object you will pass to image creator (this object contains all values you need to generate an image) and it's interface below
public class ImageSettings : IImageSettings
{
public int posX { get; set; }
public int posY { get; set; }
public StringFormat format { get; set; }
public string value { get; set; }
public Font font { get; set; }
public bool caption { get; set; }
public Font captionFont { get; set; }
}
public interface IImageSettings
{
int posX { get; set; }
int posY { get; set; }
StringFormat format { get; set; }
string value { get; set; }
Font font { get; set; }
bool caption { get; set; }
Font captionFont { get; set; }
}
public class ImageCreator : IImageCreator
{
THIS IS NEW METHOD WHICH ACCEPTS TYPE OF AN INTERFACE INSTEAD OF PARAMS
public Image CreatePreviewImg(IImageSettings imageSettings)
{
//ALL THE MAGIC HAPPENS HERE
}
THIS IS THE OLD METHOD - NO LONGER REQUIRED
public Image CreatePreviewImg(string value, int fontSize, int x, int y)
{
// Iniziate barcode font
PrivateFontCollection private_fonts = new PrivateFontCollection();
private_fonts.AddFontFile("FREE3OF9.TTF");
//Image size A4 at 300dpi
Bitmap bm = new Bitmap(width, height);
bm.SetResolution(300, 300);
// Create rectangle for the canvas
RectangleF rectBg = new RectangleF(0, 0, width, height);
// Load fonts
Font bcFont = new Font(private_fonts.Families[0], fontSize, FontStyle.Regular, GraphicsUnit.Point);
Font valueFont = new Font("Tahoma", 12, FontStyle.Regular, GraphicsUnit.Point);
// Set StringFormat for the text value
StringFormat sfValue = new StringFormat();
sfValue.LineAlignment = StringAlignment.Far;
sfValue.Alignment = StringAlignment.Center;
// Set StringFormat for the barcode string
StringFormat sfBarcode = StringFormat.GenericTypographic;
sfBarcode.FormatFlags = StringFormatFlags.NoClip;
using (Graphics g = Graphics.FromImage(bm))
{
// Create rectangle to place the barcode and text
SizeF bcStringSize = g.MeasureString("*" + value + "*", bcFont);
SizeF valueSize = g.MeasureString(value, valueFont);
RectangleF recText = new RectangleF(x, y, (float)MeasureDisplayStringWidth(g, "*" + value + "*", bcFont), (float)(bcStringSize.Height + valueSize.Height));
// Drawing the barcode and text
g.SmoothingMode = SmoothingMode.AntiAlias;
g.TextRenderingHint = TextRenderingHint.AntiAlias;
g.FillRectangle(new SolidBrush(Color.White), rectBg);
g.DrawString("*" + value + "*", bcFont, new SolidBrush(Color.Black), recText, sfBarcode);
g.DrawString(value, valueFont, new SolidBrush(Color.Black), recText, sfValue);
}
return bm;
}
}
Upvotes: 1
Reputation: 2551
But what if I want to add more objects to this image, wouldn't it be a lot easier to maintain and extent, if I used Interfaces? I would also like to elaborate my programming, by learning how to use something a little bit more complex.
That entirely depends if you are going to have multiple classes that implement the interface.
I see nothing in your code code that would warrent an interface. Have you considered reading a book on how to program in C# by chance? Reading examples is a horrible way of learning how to program, you need to understand the correct way to program, and often time that only comes from books written by people in the industry with decades worth of experience.
Upvotes: 0