|
Hi Jinal, to an extent yes this is what I'm attempting to do.
However within the wikipedia articles c# example there is this block of code;
public static IPizza CreatePizza(PizzaType pizzaType)
{
switch (pizzaType)
{
case PizzaType.HamMushroom:
return new HamAndMushroomPizza();
case PizzaType.Deluxe:
return new DeluxePizza();
case PizzaType.Hawaiian:
return new HawaiianPizza();
default:
throw new ArgumentException("The pizza type " + pizzaType + " is not recognized.");
}
}
So I still have the problem of a long winded repetitive case statement or if statement.
From what i have read if a base fruit method or property is marked virtual, and you call said method or property on some unknown fruit, C# will see which kind of fruit you really have a hold of and call ITS designated overridden version. Thus avoiding ifs and case statements but how do I get to that point?
|
|
|
|
|
I got it. There is one alternative solution.
In factory pattern you need to implement one more layer.
That is your BasePizza class, from which every type of
pizza derived.
In BasePizza you can define methods and properties as
virtual.
So for creating the object of pizza will look like following.
public static IPizza CreatePizza(PizzaType pizzaType)
{
switch (pizzaType)
{
case PizzaType.HamMushroom:
return new HamAndMushroomPizza();
case PizzaType.Deluxe:
return new DeluxePizza();
case PizzaType.Hawaiian:
return new HawaiianPizza();
default:
return new BasePizza();
}
}
The other pizza type like HamAndMushroomPizza, DeluxePizza, etc are derived
from BasePizza.
HTH
Jinal Desai - LIVE
Experience is mother of sage....
|
|
|
|
|
If you really don't want to write ifs for each new fruit you add, you can use reflection like this:
<br />
Assembly assembly = typeof(FruitBase).Assembly;<br />
Type type = assembly.GetType(name);<br />
object obj = Activator.CreateInstance(type);<br />
This code assumes that all fruit classes are defined in the same assembly as FruitBase. After this code is executed obj contains fruit selected.
You should of course add some error checking, try-catches, but the basic idea remains.
Don't forget to rate answer, that helped you. It will allow other people find their answers faster.
|
|
|
|
|
Could you possibly clarify this please Lukasz?
Where does this block of code go exactly?
Why does the type always return null, regardless of which string I pass into the assembly.GetType(name)?
|
|
|
|
|
Ok so I'm at the point now where my class file looks like this;
public class FruitBase
{
private string _name;
private string _colour;
public FruitBase()
{
}
public virtual string Name
{
get { return _name; }
set { _name = value; }
}
public string Colour
{
get { return _colour; }
set { _colour = value; }
}
public virtual void GetDefaults(FruitBase fruit)
{
fruit.GetDefaults(fruit);
}
}
public class Apple: FruitBase
{
public Apple()
{
}
public override void GetDefaults(FruitBase fruit)
{
this.Name = "Apple";
this.Colour = "Red";
}
}
and my button click event runs this
FruitBase fb = new FruitBase();
FruitBase fb2 = new FruitBase();
if (radList.SelectedValue == "Apple")
{
fb2 = new Apple();
}
else if (radList.SelectedValue == "Banana")
{
fb2 = new Banana();
}
else if (radList.SelectedValue == "Orange")
{
fb2 = new Orange();
}
else if (radList.SelectedValue == "Pear")
{
fb2 = new Pear();
}
fb.GetDefaults(fb2);
txtOuput.Text = fb.Name + " - " + fb.Colour + "/" + fb2.Name + " - " + fb2.Colour;
Now this works as the fb2.Name and colour return the correct values for the fruit type BUT a huge part of this was for me to eradicate the if statement you can see above in the click event.
So now my question is hHow do I use the radList.SelectedValue to pass the chosen FruitBase object without the if statement?
|
|
|
|
|
Instead of your ifs you should put code:
<br />
Assembly assembly = typeof(FruitBase).Assembly;<br />
Type type = assembly.GetType(name);<br />
object obj = Activator.CreateInstance(type);<br />
FruitBase fb2 = obj as FruitBase;<br />
It should work.
Oh. I forgot, that the assembly.GetType(name) expects fully qualified type name (class name with namespace: YourNamespace.Banana or something like this). I hope all fruits are in the same namespace. If they are, then instead of
Type type = assembly.GetType(name);
write
Type type = assembly.GetType(string.Format("{0}.{1}", "YourNamespace", name);
If they aren't, then move them to a single namespace
Don't forget to rate answer, that helped you. It will allow other people find their answers faster.
|
|
|
|
|
Lukasz, my man! That works a treat, exactly what I was looking for! I can't thank you enough for that, I really appreciate you taking the time to help and now I will look more into Assembly and System.Reflection in more detail.
For anyone interested here is the final code that works.
Class file;
namespace FruitBase_EG
{
public class FruitBase
{
private string _name;
private string _colour;
public FruitBase()
{
}
public virtual string Name
{
get { return _name; }
set { _name = value; }
}
public string Colour
{
get { return _colour; }
set { _colour = value; }
}
public virtual void GetDefaults()
{
this.Name = "Fruit";
this.Colour = "White";
}
}
public class Apple: FruitBase
{
public Apple()
{
}
public override void GetDefaults()
{
this.Name = "Apple";
this.Colour = "Red";
}
}
public class Banana : FruitBase
{
public Banana()
{
}
public override void GetDefaults()
{
this.Name = "Banana";
this.Colour = "Yellow";
}
}
}
And my code behind looks like this;
namespace FruitBase_EG
{
public partial class _Default : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
}
public void GetValues(object sender, EventArgs e)
{
string name = radList.SelectedValue;
Assembly assembly = typeof(FruitBase).Assembly;
Type type = assembly.GetType(string.Format("{0}.{1}","FruitBase_EG", name));
object obj = Activator.CreateInstance(type);
FruitBase fb = obj as FruitBase;
fb.GetDefaults();
txtOuput.Text = fb.Name + " - " + fb.Colour;
}
}
}
Now when the user selects a fruit using the radio button, on the click event of the Get Details button we run through the code above and it picks up the users choice and then sets the FruitBase class to which ever individual fruit class we have chosen, eventually outputting the name and colour values to the textbox
|
|
|
|
|
One more thing. The code for creating selected fruit I mean
<br />
Assembly assembly = typeof(FruitBase).Assembly;<br />
Type type = assembly.GetType(string.Format("{0}.{1}","FruitBase_EG", name));<br />
object obj = Activator.CreateInstance(type);<br />
FruitBase fb = obj as FruitBase;<br />
should be placed int try-catch block, because it uses user input, and user input isn't supposed to be trusted
And another thing: you can move setting defaults to constructor (change your fruits' classes to
public class FruitBase
{
private string _name;
private string _colour;
public FruitBase()
{
this.Name = "Fruit";
this.Colour = "White";
}
public virtual string Name
{
get { return _name; }
set { _name = value; }
}
public string Colour
{
get { return _colour; }
set { _colour = value; }
}
}
public class Apple: FruitBase
{
public Apple()
{
this.Name = "Apple";
this.Colour = "Red";
}
}
public class Banana : FruitBase
{
public Banana()
{
this.Name = "Banana";
this.Colour = "Yellow";
}
}
And now, if you remove the call fb.GetDefaults(); it should still work. And it will be more user friendly
Don't forget to rate answer, that helped you. It will allow other people find their answers faster.
|
|
|
|
|
Personally, I would never do that unless the contents of the assembly in question are unknown at compile time. The performance of code like this just blows. Even if I had to do this, I would fill a dictionary with strings as keys and factory objects/delegates as values instead of using reflection all the time.
But each to their own.
|
|
|
|
|
Personally, I would caution against using reflection. It is poor practice when you own the code.
Now to get down to the Nitty gritty, will your fruit objects perform custom actions based on the object type? It is possible that you have one of the cases for less classes and not more. The pattern below works well when you have a database of objects that really only differ Categorically as far as you are concerned. Technically it can be considered a Domain. You see it a lot when loading lists from databases for drop downs. I included the enumerator and the static Get method for use in populating and retrieving from combo boxes however there are an infinite number of ways to do it.
Since this is for an interview, this method is nice in that it circumvents many of the expected problems and gotchas with a lot less code.
public class Fruit {
private static Dictionary<string, Fruit> mFruits = new Dictionary<string, Fruit>();
private string mName;
private string mColor;
public static Fruit GetFruit(string name){
return mFruits[name];
}
public static IEnumerator<Fruit> GetFruits() {
return mFruits.Values.GetEnumerator();
}
public string Name {
get {
return mName;
}
private set {
mName = value;
}
}
public string Color {
get {
return mColor;
}
private set {
mColor = value;
}
}
private Fruit(string name, string color) {
Name = name;
Color = color;
}
static Fruit() {
mFruits.Add("Apple", new Fruit("Apple", "Red"));
mFruits.Add("Banana", new Fruit("Banana", "Yellow"));
}
}
|
|
|
|
|
Is there a single function that takes 2 string[] arrays and concatenates them together in a single string[] array?
string[] s1 = { "one", "two" };
string[] s2 = { "three", "four" };
string[] s = { "one", "two", "three", "four" };
Чесноков
|
|
|
|
|
Use CopyTo[^].
"If you think it's expensive to hire a professional to do the job, wait until you hire an amateur." Red Adair.
nils illegitimus carborundum
me, me, me
|
|
|
|
|
<br />
System.Collections.Generic.List<string> lst = new System.Collections.Generic.List<string>();<br />
lst.AddRange(s1);<br />
lst.AddRange(s2);<br />
string[] s = new string[lst.Count];<br />
lst.CopyTo(s);<br />
lst.Clear();<br />
lst = null;<br />
|
|
|
|
|
simple table management
string[] s = new string[s1.Length + s2.Length];
int _sCounter = 0;
for(int i=0;i<s1.Length;i++)
s[_sCounter++] = s1[i];
for(int i=0;i<s2.Length;i++)
s[_sCounter++] = s2[i];
|
|
|
|
|
Chesnokov Yuriy wrote: Is there a single function that takes 2 string[] arrays and concatenates them together in a single string[] array?
I think following function will do the stuff, right?
public static string[] ConcateArray(string[] s1, string[] s2)
{
string[] s = new string[s1.Length + s2.Length];
s1.CopyTo(s, 0);
s2.CopyTo(s, s1.Length);
return s;
}
Just call the method as
string[] s = ConcateArray(s1, s2);
Knock out 't' from can't, you can if you think you can.
|
|
|
|
|
|
|
Hi,
I am trying to read a 32-bit bitmap file and save it another place as 24-bit,
i tried this code but the saved bitmap i get is 32-bit
ImageCodecInfo _codedInfo = GetEncoderInfo("image/bmp");
System.Drawing.Imaging.Encoder _encoder = System.Drawing.Imaging.Encoder.ColorDepth;
EncoderParameters _encoderParameters = new EncoderParameters(1);
EncoderParameter _encoderParameter = new EncoderParameter(_encoder, 24L);
_encoderParameters.Param[0] = _encoderParameter;
System.Drawing.Bitmap _bitmap = new System.Drawing.Bitmap(_filename);
_bitmap = new System.Drawing.Bitmap(_bitmap.GetThumbnailImage(16, 16, myCallback, IntPtr.Zero));
_bitmap.Save(_newFileName,_codedInfo, _encoderParameters);
Please HELP, Regards
|
|
|
|
|
I found the solution in this code, but i discovered another problem that i need help with please,
I need to make sure that the saved 24-bit file is a DIB file, how can i do that?
System.Drawing.Bitmap _bitmap = new System.Drawing.Bitmap(_filename);
System.Drawing.Bitmap _bitmap24 =
new System.Drawing.Bitmap(16,16,System.Drawing.Imaging.PixelFormat.Format24bppRgb);
_bitmap = new System.Drawing.Bitmap(_bitmap.GetThumbnailImage(16, 16, myCallback, IntPtr.Zero));
for (int i = 0; i < _bitmap.Width; i++)
for (int j = 0; j < _bitmap.Height; j++)
{
System.Drawing.Color _tmpColor = _bitmap.GetPixel(i, j);
_bitmap24.SetPixel(i,j,_tmpColor);
}
_bitmap24.Save(_newFileName);
AddImage(_newFileName);
|
|
|
|
|
On some forms the OnShown event won't be raised and I was not able to figure out why, this is most strange because it works fine on most cases and I use a class that inherits the Form class and handles the event for me, so there should be no way for me to mess up with the event handling.
Did anybody experience this problem?? Were you able to fix it?? I'd be most thankful if anyone could offer a piece of advise so I can solve this.
|
|
|
|
|
how to take the quick book data into my application
|
|
|
|
|
I guess you need to read it in some manner and then process it in some manner. Your question is not very clear.
It's time for a new signature.
|
|
|
|
|
Exchange Web Services API
Well I just can't figure this out. I'm trying to pull a list of contacts located in public folders of exchange. I used this code before and it isn't work now.
String fpfolderPath = path;
Folder PfRoot = Folder.Bind(exh, WellKnownFolderName.PublicFoldersRoot);
String[] faFldArray = fpfolderPath.Split('/');
Folder tfTargetFolder = PfRoot;
for (int lint = 1; lint < faFldArray.Length; lint++)
{
FolderView fview = new FolderView(1);
SearchFilter sf = new SearchFilter.IsEqualTo(FolderSchema.DisplayName, faFldArray[lint]);
FindFoldersResults ffResult = exh.FindFolders(tfTargetFolder.Id, sf, fview);
if (ffResult.TotalCount == 0)
tfTargetFolder = null;
else
tfTargetFolder = ffResult.Folders[0];
}
It fails here:
FindFoldersResults ffResult = exh.FindFolders(tfTargetFolder.Id, sf, fview);
With:
Exception Details: Microsoft.Exchange.WebServices.Data.ServiceResponseException: The request failed schema validation: The required attribute 'Value' is missing.
I've searched and searched google and came up with nothing. I did found an article talking about how Microsoft changes something from the RTM version and the SP1 version? I am running the latest Exchange 2007 and downloaded the latest Exchange Web Services API
Any ideas?
|
|
|
|
|
Hi All,
I am using a Chart control in VS 2010 .Can any one help me which property of this control allow me to Name my X and Y axis.
The Values are defined by for instance Series("Test").XValueMember. I would like to name my X axis as 'Hour' and Y axis as 'Revenue'
Can you advice please?
Many thanks
|
|
|
|
|