-->
These old forums are deprecated now and set to read-only. We are waiting for you on our new forums!
More modern, Discourse-based and with GitHub/Google/Twitter authentication built-in.

All times are UTC - 5 hours [ DST ]



Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 3 posts ] 
Author Message
 Post subject: How to use static typing instead of property name strings ?
PostPosted: Tue Feb 06, 2007 10:35 am 
Newbie

Joined: Wed Aug 02, 2006 6:11 am
Posts: 8
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 ?


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 06, 2007 12:05 pm 
Regular
Regular

Joined: Mon May 16, 2005 2:15 pm
Posts: 59
I see two options. Both require manual maintenence however they will allow you to use strongly typed members and code completion.

The first is to create an Enum in each of your business objects with each persistable property listed. So, for example in a Person business object you might have:

Code:
public enum Fields
{
   firstName, middleName, lastName
}

Then, in your query you can use customer.Fields.firstName.ToString(). Of course, as you see you need to use ToString() all the time.

The second method would be to create a contained class in your customer class (or struct) that had string constants... something like:

Code:
public class Fields
{
   public const string firstName = "firstName";
   public const string lastName = "lastName";
}


Then, in your query you can use customer.Fields.firstName. In this case you don't need to use ToString() since it will return a string. On advantage here is that you can change the field name without changing the string constant, and not have to change all your code.

These will need to be maintained by hand... Or, you could possibly code generate them and make them external classes perhaps naming the class CustomerFields or something.

Hth,
BOb


Top
 Profile  
 
 Post subject:
PostPosted: Tue Feb 06, 2007 12:20 pm 
Regular
Regular

Joined: Tue Mar 15, 2005 12:38 pm
Posts: 73
Location: Bucharest
And the winner is .... Ayende :)
(Off topic: seems like I should be issuing some invoices for free advertising)

Jokes are over, Ayende did a nice work with his query generator:

Download from:
http://www.ayende.com/projects/nhiberna ... loads.aspx

Short tutorial (there are other on his blog)
http://www.ayende.com/Blog/archive/7186.aspx

_________________
Dragos


Top
 Profile  
 
Display posts from previous:  Sort by  
Forum locked This topic is locked, you cannot edit posts or make further replies.  [ 3 posts ] 

All times are UTC - 5 hours [ DST ]


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum

Search for:
© Copyright 2014, Red Hat Inc. All rights reserved. JBoss and Hibernate are registered trademarks and servicemarks of Red Hat, Inc.