I would like to be able to avoid all strings in queries, to avoid runtime problems when refactoring property names, which can not be changed automatically by Visual Studio when the property names occurr in strings.
In other words, instead of this kind of code:
Code:
string catName = ...
ICriteria crit = session.CreateCriteria(typeof(Cat));
crit.Add(Expression.Eq("Name", catName)); // I want to get rid of the unsafe string usage when refering to a property name
I would rather like to use something like this:
Code:
string catName = ...
ICriteria crit = session.CreateCriteria(typeof(Cat));
crit.Add(Expression.Eq(ReflectionUtilityHelper.GetPropertyName((new Cat()).Name), catName)); // no string here...
Though, I do not think it is possible to create a class/method "ReflectionUtilityHelper.GetPropertyName" which could retrieve the string "Name" from the actual parameter, which is simply a string which will become a local variable in the formal parameter of that method...
However, has anyone come up with a good workaround for how to avoid all strings in queries to instead use static typing and property names that can be renamed/refactored without getting runtime exceptions ?
Here is one approach I have found, but would like something better if possible:
Code:
string catName = ...
ICriteria crit = session.CreateCriteria(typeof(Cat));
Cat myCat = new Cat();
crit.Add(Expression.Eq(myCat.GetPropertyName(myCat.Name), catName));
// 'myCat.GetPropertyName(myCat.Name)' will return "Name" when Cat is implemented as below
class Cat : BaseClassEntity
{
private string name;
public string Name
{
get {
base.SetCurrentlyInvokedPropertyMethod(MethodBase.GetCurrentMethod().Name);
return name;
}
set { name = value; }
}
}
class BaseClassEntity
{
// The actual property should be used DIRECTLY in the invocation of this
// method, i.e. do NOT save it in a local variable
// Examples:
// Correct usage of this method:
// 'myEntity.GetPropertyName(myEntity.SomeProperty)'
// Incorrect usage of this method:
// 'string someProperty = myEntity.SomeProperty'
// 'string otherProperty = myEntity.OtherProperty'
// 'myEntity.GetPropertyName(someProperty)'
public string GetPropertyName(string propertyName)
{
return currentlyInvokedPropertyName;
}
private string currentlyInvokedPropertyName;
protected void SetCurrentlyInvokedPropertyMethod(string currentlyInvokedPropertyMethodName)
{
// for example: currentlyInvokedPropertyMethodName="get_Name"
// ( if this method was invoked from the property "Name", using "MethodBase.GetCurrentMethod()" )
// now eliminate the "get_" prefix to get the property name:
this.currentlyInvokedPropertyName = currentlyInvokedPropertyMethodName.Substring(4);
}
}
The whole point of the above stuff is to be able to refactor/rename properties, for example the illustrated Name property, without still having the property occurring in strings which can not be automatically refactored.
The cat object above is just a locally existing variable used for defining the property to the criteria object, so therefore there should not be any problems with multiple threads refering to the same cat criteria.
However, I would be interested to see if anyone else (who just like me hates string based API's in a statically typed OO language) has come up with a better solution ?