Case-insentive datamapper Case-insentive datamapper
Old forum URL: forums.lhotka.net/forums/t/2585.aspx
kobruleht posted on Sunday, March 25, 2007
I use modified Rockford Lhotka excellent SetPropertyValue()
from DataMapper class to load objects from database.
My entity object property names are mixed case.
DataReader returns lower-case only column names.
So SetPropertyValue() cannot map columns to property names.
How to change this code so that it does not depend on the propertyName case ?
<pre>
/// <summary>
/// Sets an object's property with the specified value,
/// coercing that value to the appropriate type if possible.
/// </summary>
/// <param name="target">Object containing the property to set.</param>
/// <param name="propertyName">Name of the property to set.</param>
/// <param name="value">Value to set into the property.</param>
public static void SetPropertyValue(
object target, string propertyName, object value)
{
PropertyInfo propertyInfo =
target.GetType().GetProperty(propertyName);
if (value == null)
propertyInfo.SetValue(target, value, null);
else
{
Type pType =
Utilities.GetPropertyType(propertyInfo.PropertyType);
Type vType =
Utilities.GetPropertyType(value.GetType());
if (pType.Equals(vType))
{
// types match, just copy value
propertyInfo.SetValue(target, value, null);
}
else
{
// types don't match, try to coerce
if (pType.Equals(typeof(Guid)))
propertyInfo.SetValue(
target, new Guid(value.ToString()), null);
else if (pType.IsEnum && vType.Equals(typeof(string)))
propertyInfo.SetValue(target, Enum.Parse(pType, value.ToString()), null);
else if (pType.IsEnum && vType.Equals(typeof(decimal)))
propertyInfo.SetValue(target,
Enum.Parse(pType, value.ToString()), null);
else
propertyInfo.SetValue(
target, Convert.ChangeType(value, pType), null);
}
}
}
}
}
</pre>
Bayu replied on Monday, March 26, 2007
Hi!
Make use of TypeDescriptor (available from System.ComponentModel namespace):
Dim pDescriptors As PropertyDescriptorCollection = TypeDescriptor.GetProperties(objectType)
Dim pDescriptor As PropertyDescriptor = pDescriptors.Find(propertyName, True)
(It's VB code)
- the first line will give you a searchable (!) collection.
- the second line invokes Find on this collection where the second argument sets ignoreCase to True
You can then retrieve the name of the property in correct casing from the found descriptor:
Dim pName As String = pDescriptor.Name
This name can then be fed to your call that returns the PropertyInfo object:
Dim pInfo As PropertyInfo = target.GetType().GetProperty(pName)
And you should be good to go!
Bayu
kobruleht replied on Monday, March 26, 2007
How about simply using:
PropertyInfo propertyInfo =
target.GetType().GetProperty(propertyName, System.Reflection.BindingFlags.Instance |
System.Reflection.BindingFlags.IgnoreCase | System.Reflection.BindingFlags.Public)
This is simpler than you approach.
Can Racky add this change to this method ?
Bayu replied on Wednesday, March 28, 2007
Ah,
Good one! Much cleaner than what I proposed.
Bayu
ajj3085 replied on Wednesday, March 28, 2007
The only problem with that change is if you actually have two properties which differ by casing only. While I agree it shouldn't be done and is not CLS compliant, if someone where to do that, they'd have mysterious bugs in their code.
Bayu replied on Thursday, March 29, 2007
ajj3085: The only problem with that change is if you actually have two properties which differ by casing only. While I agree it shouldn't be done and is not CLS compliant, if someone where to do that, they'd have mysterious bugs in their code.
Thankfully that is impossible in VB.
Really is an ugly remnant from C(++) and co imo.
;-)
Bayu
ajj3085 replied on Thursday, March 29, 2007
Personally, I like the case sensitivity. I use this to seperate fields from properties..
public string MyString {
get {
return myString; }
set { myString =
value; }
private string myString;
I dislike using the _ or having to change the name of the field because a language is case insensitive.
Obviously, my opinion.
Skafa replied on Thursday, March 29, 2007
I dó like using te 'm' or '_' prefix for private fields. For readability (you can quickly see private fields in your code), to avoid mistakes (I use VB ánd C#), but far most because you get a nice fast accessable list in IntelliSense when beginnen typing :-)
ajj3085 replied on Thursday, March 29, 2007
Everybody has their own style. What is the 'm' supposed to mean though? We used to use s for string, i for integer, etc., but that was in the classic asp days. We used m for module level variables... but that doesn't make sense to me anymore because we don't have modules, we have classes, namespaces and assemblies.
Skafa replied on Thursday, March 29, 2007
I don't know for sure, but you see it in a lot of VB code. It could be something like member or something.
Bayu replied on Thursday, March 29, 2007
ajj3085: What is the 'm' supposed to mean though?
I think there can only be one correct answer to this .........
It stands for MMMMMMMMMMMMMicrosoft of course!........ what'd ya think? ;-p
It's the 'M' of Making Money and for doing things Mightily diffferently, namely the MMMMicrosoft way!
;-)
No, I always thought it was for 'my', as in a a possessive noun that refers to the class. So it was supposed to be used for class-level (i.e. private) variables. You know, there were those days suddenly everything became 'mine' (as if it was Microsoft's before), think of the introduction of My Computer, My Documents, My Videos, My .. My, My .... (say this several times and you start to sound like those pelicans from Finding Nemo ;-) ).
Bayu
Copyright (c) Marimer LLC