Sunday, November 21, 2010
Open source Zip library
http://dotnetzip.codeplex.com/
Tuesday, October 26, 2010
Tuesday, October 19, 2010
Get the field size in the entity
In the entity framework, the diagram shown in the Visual Studio contains field information of all tables. You may get the field size that stores in the diagram by using the following method:
public static int GetMaxLength(ObjectContext p, string tb_name, string fld_name) { if (p == null) { throw new ArgumentNullException(); } MetadataWorkspace w = p.MetadataWorkspace; var items = w.GetItems(DataSpace.CSpace); //i.Properties["tb_name"].TypeUsage.Facets["MaxLength"].Value var v = items.Where(i => string.Compare(i.Name, tb_name, true) == 0); EntityType et = v.First(); object obj = et.Properties[fld_name].TypeUsage.Facets["MaxLength"].Value; if (obj != null) { string len = obj.ToString(); if (string.Compare(len, "max", true) == 0) { return -1; } else { int max_len = Int32.Parse(len); return max_len; } } else { return 0; } }
Linq literals
http://msdn.microsoft.com/en-us/library/bb399176.aspx
Saturday, October 16, 2010
Efficient way to add new parameter
It is so common that we need to add new parameter to the method during the system development or maintenance. Adding new parameter will become unavoidable when the business requirements changed.
For example, you have a method call Process which takes 2 integer parameters as shown below:
public int Process(int a, int b) { int result = a + b; return result; }
Now, what if you have to add a new integer parameter to this method? Normally, we will just simply add a parameter as we used to do. So, the new method will be look like this:
public int Process(int a, int b, int c) { int result = a + b + c; return result; }
Again, you have to add a new parameter (i.e., fourth parameter) due to the business process changed. OK. I think we need an efficient way to do this.
To avoid adding new parameter to the method (i.e., changing the method signature), we have to pass a struct or a object to the method. To do this,
1. Declare a class call MyParam:
public class MyParam { public int a { get; set; } public int b { get; set; } public int c { get; set; } }
2. Change the Process method to take in the MyParam class instead of the 3 parameters:
public int Process(MyParam p) { int result = p.a + p.b + p.c; return result; }
3. If you want to the fourth parameter, you have to add a new property instead of parameter. Also, the caller will no longer require to be modify because the method signature does not change.
The new MyParam class will be look like this:
public class MyParam { public int a { get; set; } public int b { get; set; } public int c { get; set; } public int d { get; set; } //<== new parameter. }
Of course, the implementation within the Process method must be modify and the caller must assign the value to property 'd' before passing it to the Process method.
Thursday, September 23, 2010
A substitute of switch.. case
Solution: you may try to replace the 'switch..case' with Dictionary + reflection. By using this plug and play design, you will be able to expand your program easily.
For example, you have a class call ProcessSwitches which handles the process request:
public class ProcessSwitchesOf course, whenever you need to provide a new service, you have to add a new 'case' and a method specifically for that purpose. In case you have a very long list of services, you may not want to see a many hundred lines of cases here.
{
public string Process(int process_index)
{
string result = string.Empty;
switch (process_index)
{
case 0:
result = this.Cleaning();
break;
case 1:
result = this.Polishing();
break;
//other processes go here...
default:
result = "underdefined";
break;
}
return result;
}
string Cleaning()
{
return "Cleaning process.";
}
string Polishing()
{
return "Polishing process";
}
// many other methods here...
}
To overcome this problem, we need to define an interface which will serve the common method call. Then, each service will be converted from method (ie, ProcessSwitches.Cleaning and ProcessSwitch.Polishing) to class individually.
public interface IProcessAfter converting the methods to classes, we need to create a registry (or repository) to store the service index and class mapping.
{
string Execute();
}
public class Cleaning : IProcess
{
public string Execute()
{
return "cleaning..";
}
}
public class Drying : IProcess
{
public string Execute()
{
return "drying..";
}
}
public class ProcessRegistry : DictionaryThe final step will be replacing the 'switch..case' by the ProcessRegistry that we have created. Since the ProcessRegistry was inherited from Dictionary class, you may retrieve the class type that you have setup in the ProcessRegistry.Init method.
{
public ProcessRegistry()
{
this.Init();
}
void Init()
{
this.Add(0, typeof(Cleaning));
this.Add(0, typeof(Polishing));
//you may add more other process here.
//...
}
}
public class ProcessSwitchesNewNow, what is the benefit you receive from this design?
{
ProcessRegistry registry = new ProcessRegistry();
public string Process(int process_index)
{
string result = string.Empty;
Type type;
// now, you may replace the 'switch..case' with Dictionary class.
// which allows you to provide more services without modifying this method.
if (registry.TryGetValue(process_index, out type))
{
// instantiate the object.
object obj = Activator.CreateInstance(type);
// cast it as IProcess interface.
IProcess process = obj as IProcess;
if (process != null)
{
// execute the process.
result = process.Execute();
}
}
return result;
}
}
Benefits:
- You can create and test the service class individually or pass the class development to your team member.
- Easier to increase the number of cases without have the mess around within the 'switch..case' statement. What you need to do is to add a new line in the ProcessRegistry.Init method. Anyone can do it easily.
- The service classes (such as Cleaning and Polishing) can be reuse without have to dismantle the 'switch..case'. Just setup a new registry class and load the necessary class types.
Of course, everything comes in costs. There are disadvantages in this design:
- You might have too many classes.
- The program might run slower due to the use of reflection (ie, Activator) to instantiate the class.
Plug and play design
Solution: this problem can be easily resolve in C# by using interface and implement it into various classes.
For example, we need a process that is responsible for cleaning and then drying. In order to achieve the add-on concept, first, we need to define an interface:
public interface IProcessBoth the cleaning and drying process must be develop as class instead of method. The classes must implement IProcess interface:
{
// execute the process.
void Execute();
}
public class Cleaning : IProcess
{
public void Execute()
{
System.Console.WriteLine("cleaning..");
}
}
public class Drying : IProcess
{
public void Execute()
{
System.Console.WriteLine("drying..");
}
}
Finally, we need to create a class that executes the cleaning and drying process:
public class RunAllProcessThe reason of using Type list instead of IProcess list is that the object instance will not be created upon adding. It will be instantiate before you execute the process. This is to avoid executing the codes in the class's constructor (if any) which may occupy the memory.
{
public void Run()
{
// iniatialize the list to store the Type
List< Type> list = new List< Type>();
list.Add(typeof(Cleaning));
list.Add(typeof(Drying));
// you may add more classes here in
// the future with ease...
IProcess process;
foreach (Type item in list)
{
// instantiate the object at runtime.
process = (IProcess)Activator.CreateInstance(item);
// execute the process:
process.Execute();
}
}
}
After a while, the user might want to add a new process call polishing. This can be done easily.
Declare a new class:
public class Polishing : IProcessThen, add a new process:
{
public void Execute()
{
System.Console.WriteLine("polishing..");
}
}
public class RunAllProcess
{
public void Run()
{
...
list.Add(typeof(Cleaning));
list.Add(typeof(Drying));
list.Add(typeof(Polishing)); //<==== add the new process here.
...
}
}