Archive
A generic cloning method
Hey all,
As you know I’m big on Reflection, and big on Generics…now, here’s a method that combines the two for a neat little cloning tool.
Let’s assume we have a base object we use for objects, and let’s call it DataObject. Anything can derive from this object, and in addition, I’m going to add the following method to allow me to “clone” the properties of my current object onto the properties of any other object, provided the Name and Type of the property match.
Notice that I am using the generic t notation for a generic object, and this becomes a generic method.
public class DataObject
{
public t Clone<t>()
{
//reflection based clone
Type tType = typeof(t);
t item = (t) Activator.CreateInstance(tType);
PropertyInfo[] props = tType.GetProperties();
foreach (PropertyInfo prop in props)
{
try
{
prop.SetValue(item, prop.GetValue(this, null), null);
}
catch { }
}
return item;
}
}
Ok, now that that’s done, let’s create two more classes, a Dog, and a Cat.
public class Cat : DataObject
{
private string _name;
public string Name
{
get { return _name;}
set { _name = value;}
}
private string _color;
public string Color
{
get { return _color;}
set { _color= value;}
}
}
public class Dog : DataObject
{
private string _name;
public string Name
{
get { return _name;}
set { _name = value;}
}
private string _color;
public string Color
{
get { return _color;}
set { _color= value;}
}
}
Ok, let’s create a Cat.
Cat cat = new Cat();
cat.Name = “Fluffy”;
cat.Color = “Orange”;
Now that we have that, we can create a Dog from the Cat:
Dog dog = cat.Clone<Dog>();
Once this method is called, the dog will have the exact same properties as the cat…this is useful in particular if you are adjusting properties on objects that are similar enough while in a loop (for example, you are looping on creating email objects that you are placing in a list) and you find yourself in a position where just overriding the properties on the current object won’t work.
Happy cloning!
Rob
Sorting Generic Lists
One of the things I like best about the use of Generics is the ability to define your own sorting functionality and apply it to a List. Much in the same way you can predefine your own Find mechanism using predicates, you can establish a way to sort your list of Generics when they don’t contain native datatypes such as int or string.
In this example we’ll take a look at how to sort a Generic list using the IComparer interface.
First of all, let’s establish a class of type Dog, and give it three properties. The first property we’ll call Species, and the next property we’ll call Age. The final property we’ll call Name.
public class Dog
{
private int _age;
private string _species;
private string _name;
public string Name
{
get{ return _name; }
set{ _name = value; }
}
public int Age
{
get{ return _age; }
set{ _age = value; }
}
public string Species
{
get{ return _species; }
set{ _species = value; }
}
}
Now that we have that we can create a list of four dogs like so:
Dog max = new Dog();
max.Age = 8;
max.Species = “Labrador”
max.Name = “Max”
Dog spike = new Dog();
spike.Age = 3;
spike.Species = “Rottweiler”
spike.Name = “Spike”
Dog princess = new Dog();
princess.Age = 5;
princess.Species = “Poodle”
princess.Name = “Princess”
Dog wolfy = new Dog();
wolfy.Age = 10;
wolfy.Species = “Husky”
wolfy.Name = “Wolfy”
List<Dog> dogs = new List<Dog>();
dogs.Add(max);
dogs.Add(spike);
dogs.Add(princess);
dogs.Add(wolfy);
Now I’d like to be able to sort a few different ways, and I can do this by providing an object that implements an IComparer interface of type Dog, like so:
public class DogAgeComparer : IComparer<Dog>
{
}
Now that I have my class, let’s implement the interface:
public class DogAgeComparer : IComparer<Dog>
{
#region IComparer<Dog> Members
public int Compare(Dog x, Dog y)
{
return x.Age.CompareTo(y.Age);
}
#endregion
}
Now that we have that, we can sort our list based on the dog’s age:
dogs.Sort(new DogAgeComparer());
This will sort the list in the appropriate order of age.
Similarly, we can use a different object for Name and have that available as well.
public class DogNameComparer : IComparer<Dog>
{
#region IComparer<Dog> Members
public int Compare(Dog x, Dog y)
{
return x.Name.CompareTo(y.Name);
}
#endregion
}
Now sort the list:
dogs.Sort(new DogNameComparer());
And there you have it! Quick and easy sorting of your objects.
Happy sorting!
Rob
Stack Reflections
If you haven’t noticed by my choice of presentation topics, I’m a big fan of Reflection. I like the flexibility and scalability it allows me to build into my applications. There are also some neat little tricks you can use with it, in conjunction with the stack trace, to better track your errors and debugging statements.
First of all, how would you like to be able to write a trace statement that shows your methods called without having to remember to code the method names? This can be accomplished by “walking the stack trace” during a method call and using the reflected method information from the stack to determine what method called your function. It works something like this:
I’m going to write a method called TraceMethodStart with no parameters. This method will load up the stack trace, walk the stack frame back one level, and then write out to Trace the method name and module name of the method that called the TraceMethodStart function.
public void TraceMethodStart()
{
System.Diagnostics.StackTrace currentStack = new System.Diagnostics.StackTrace();
string sMethod = “Unknown method”;
string sClass = “Unknown type”;
//make sure I have frames
if (currentStack.FrameCount > 0)
{
//get the method of the frame one up from me
System.Reflection.MethodBase oBase = currentStack.GetFrame(1).GetMethod();
sMethod = oBase.Name;
sClass = oBase.DeclaringType.ToString();
}
if (System.Web.HttpContext.Current != null)
System.Web.HttpContext.Current.Trace.Write(“Starting: ” + sClass + ” ” + sMethod);
}
Now in my GetRob() function I do this:
namespace Sltc
{
public class Rob
{
public void GetRob()
{
TraceMethodStart();
}
}
}
And a “Starting: Sltc.Rob GetRob” will appear in our trace statements.
Now that’s useful. But it would be even more useful if we knew what was being passed to the function for parameters. Using the params keyword we can extend this function to accept a variable list of arguments so that we can call it from anywhere in our code and get passed any number of arguments. This will allow us to include the variables the function was given when it was called.
public void TraceMethodStart(params object[] oParms)
{
System.Diagnostics.StackTrace currentStack = new System.Diagnostics.StackTrace();
string sMethod = “Unknown method”;
string sClass = “Unknown type”;
//make sure I have frames
if (currentStack.FrameCount > 0)
{
//get the method of the frame one up from me
System.Reflection.MethodBase oBase = currentStack.GetFrame(1).GetMethod();
sMethod = oBase.Name;
sClass = oBase.DeclaringType.ToString();
}
if (System.Web.HttpContext.Current != null)
System.Web.HttpContext.Current.Trace.Write(“Starting: ” + sClass + ” ” + sMethod);
foreach(object obj in oParms)
{
if (System.Web.HttpContext.Current != null)
System.Web.HttpContext.Current.Trace.Write(“Parm: ” + oParm.ToString());
}
}
Now if you are in a method like so, you can do this:
function MyMethod(string s, int i)
{
TraceMethodStart(s, i);
}
Another handy thing you can do with this is to grab the cause for exceptions. A lot of times the stack trace is huge and it’s difficult to track down or even remember to write code to track where your exceptions are occuring. However, if you were to create your own exception, you could use a similar code sequence to grab the cause of the trouble:
public class SLTCException : System.Exception
{
private string _sClass = “Unknown”;
private string _sMethod = “Unknown”;
public SLTCException() : base()
{
System.Diagnostics.StackTrace currentStack = new System.Diagnostics.StackTrace();
if (currentStack.FrameCount > 0)
{
System.Reflection.MethodBase oBase = currentStack.GetFrame(1).GetMethod();
_sMethod = oBase.Name;
_sClass = oBase.DeclaringType.ToString();
}
}
}
Happy stacking!
Rob
