Refactor-safe Property Access Using Reflection?

J

jehugaleahsa

Hello:

I have been seeing a lot of cool examples where developers are using
expression trees to make refactoring and reflection go hand-in-hand. I
am wondering if a trick like that could be performed with properties.
I don't have much first-hand experience with expression trees.

In my system, we have GUI and non-GUI applications. I have a service
layer that returns data objects. When I attach my data objects to a
Windows Form, I decorate them to support INotifyPropertyChanged. The
decorator has methods for getting and setting property values of the
decorated data object.

I have a method that looks like this:

void SetValue<T>(string propertyName, T value) { ... }

This method goes into the decorated data object and sets it's
property. It then raises a PropertyChanged event (passing the property
name).

Now say I change my data object's property names. With the
implementation above, my decorator throws an exception because the
property cannot be found (because it is referring to the old name).

I was hoping to alleviate this by replacing my string with something
spiffy. I was wondering if anyone could think of a way to do it. We're
dealing with a user interface here, so performance isn't that
important.

Thanks,
Travis
 
P

Peter Duniho

Hello:

I have been seeing a lot of cool examples where developers are using
expression trees to make refactoring and reflection go hand-in-hand. I
am wondering if a trick like that could be performed with properties.
I don't have much first-hand experience with expression trees.

In my system, we have GUI and non-GUI applications. I have a service
layer that returns data objects. When I attach my data objects to a
Windows Form, I decorate them to support INotifyPropertyChanged. The
decorator has methods for getting and setting property values of the
decorated data object.

I have a method that looks like this:

void SetValue<T>(string propertyName, T value) { ... }

This method goes into the decorated data object and sets it's
property. It then raises a PropertyChanged event (passing the property
name).

Now say I change my data object's property names. With the
implementation above, my decorator throws an exception because the
property cannot be found (because it is referring to the old name).

I was hoping to alleviate this by replacing my string with something
spiffy. I was wondering if anyone could think of a way to do it. We're
dealing with a user interface here, so performance isn't that
important.

How tied to the original data object is your decorator? Do you _have_ to
use reflection? Or is that a convenience, so that you don't have to
explicitly type mappings between strings and actual properties?

If the latter, then it seems to me that one alternative would be to give
up on the convenience (which is costing you in reflection overhead
anyway), and just do the explicit mapping. It could even be as simple as
a big switch (which the compiler will translate into something efficient
anyway). Then, since your decorator is explicitly calling named members
of the decorated class, refactoring catches it.

If you are trying to use the same decorator class for all decorated types,
and thus reflection is more of a necessity than a convenience, then I
don't see an easy way around that. If your decorated types can change and
you don't want to have to go back and fix up all the string-based
accessors through decorators, it seems to me you'll have to provide for a
separate mechanism to do the mapping. Either strictly string-based, which
provides zero tie-in to the refactoring tools, or something that _is_
inherently tied to the named members of the decorated classes, in which
case it begs the question: if you have to tie something to the decorated
class, why not just make that the decorator itself?

I suppose yet another alternative would be to use a custom code attribute
to mark the properties with the mapped name(s). But if you have to embed
the client-side name used for the properties in the data object class
anyway, via an attribute, then the question that is begged _there_
becomes: why rename the property at all, if it's going to cause such a
headache and require this additional complexity?

If you have a concise-but-complete code example that clearly illustrates
the relationships between your classes here, that might help. If you can
include a link to one or more of the examples you referred to in which
"developers are using
expression trees to make refactoring and reflection go hand-in-hand", that
might help too. I'm not really sure what you mean there.

Pete
 
J

jehugaleahsa

How tied to the original data object is your decorator?  Do you _have_ to  
use reflection?  Or is that a convenience, so that you don't have to  
explicitly type mappings between strings and actual properties?

If the latter, then it seems to me that one alternative would be to give  
up on the convenience (which is costing you in reflection overhead  
anyway), and just do the explicit mapping.  It could even be as simple as  
a big switch (which the compiler will translate into something efficient  
anyway).  Then, since your decorator is explicitly calling named members  
of the decorated class, refactoring catches it.

If you are trying to use the same decorator class for all decorated types,  
and thus reflection is more of a necessity than a convenience, then I  
don't see an easy way around that.  If your decorated types can change and  
you don't want to have to go back and fix up all the string-based  
accessors through decorators, it seems to me you'll have to provide for a 
separate mechanism to do the mapping.  Either strictly string-based, which  
provides zero tie-in to the refactoring tools, or something that _is_  
inherently tied to the named members of the decorated classes, in which  
case it begs the question: if you have to tie something to the decorated  
class, why not just make that the decorator itself?

I suppose yet another alternative would be to use a custom code attribute 
to mark the properties with the mapped name(s).  But if you have to embed  
the client-side name used for the properties in the data object class  
anyway, via an attribute, then the question that is begged _there_  
becomes: why rename the property at all, if it's going to cause such a  
headache and require this additional complexity?

If you have a concise-but-complete code example that clearly illustrates  
the relationships between your classes here, that might help.  If you can  
include a link to one or more of the examples you referred to in which  
"developers are using
expression trees to make refactoring and reflection go hand-in-hand", that  
might help too.  I'm not really sure what you mean there.

Pete- Hide quoted text -

- Show quoted text -

Yes. I have thought about calling the the underlying methods
explicitly and have allowed it to be done (raising PropertyChanged
manually). Even if I do call it manually, the PropertyChanged event
still needs passed the name of the property. I don't think there
really is a way to provide that property name without manually passing
in the string.

I was looking into the expression trees a little more and am not sure
what I was talking about. I guess you can get at the name of a method
in a type-safe manner. The examples I saw weren't using reflection
under the hood, simply lambdas and type inference.
 
K

kndg

[...]
Now say I change my data object's property names. With the
implementation above, my decorator throws an exception because the
property cannot be found (because it is referring to the old name).

I was hoping to alleviate this by replacing my string with something
spiffy. I was wondering if anyone could think of a way to do it. We're
dealing with a user interface here, so performance isn't that
important.

Thanks,
Travis

Hi Travis,

If I understand your requirement correctly, instead embedding the string
directly in code, you need to pass your method with your property name.
I'm not sure whether it can be done using Expression Tree or not, but it
can be done using reflection.

Just declare your PropertyInfo object on your class,

private static PropertyInfo[] properties = typeof(MyObject).GetProperties();

Then, pass the properties[0].Name to your SetValue method.
Take note that the array is indexed base on how you arrange your
properties.

Regards.
 
K

Konstantin Novikov

static class PropertyName<TClass>
{
public static string Get<TPropertyReturnValue>(Expression<Func<TClass, TPropertyReturnValue>> expr)
{
var memberExpr = expr.Body as MemberExpression;
if (memberExpr == null)
throw new ArgumentException("Expression must contain the only member access operation", "expr");
return memberExpr.Member.Name;
}
}

class MyClass
{
public int MyProperty { get; set; }
}

// ...

PropertyName<MyClass>.Get(x => x.MyProperty); // returns "MyProperty"



Peter Duniho wrote:

Re: Refactor-safe Property Access Using Reflection?
17-Aug-09

How tied to the original data object is your decorator? Do you _have_ t
use reflection? Or is that a convenience, so that you do not have t
explicitly type mappings between strings and actual properties

If the latter, then it seems to me that one alternative would be to giv
up on the convenience (which is costing you in reflection overhea
anyway), and just do the explicit mapping. It could even be as simple a
a big switch (which the compiler will translate into something efficien
anyway). Then, since your decorator is explicitly calling named member
of the decorated class, refactoring catches it

If you are trying to use the same decorator class for all decorated types
and thus reflection is more of a necessity than a convenience, then
do not see an easy way around that. If your decorated types can change an
you do not want to have to go back and fix up all the string-base
accessors through decorators, it seems to me you will have to provide for
separate mechanism to do the mapping. Either strictly string-based, whic
provides zero tie-in to the refactoring tools, or something that _is
inherently tied to the named members of the decorated classes, in whic
case it begs the question: if you have to tie something to the decorate
class, why not just make that the decorator itself

I suppose yet another alternative would be to use a custom code attribut
to mark the properties with the mapped name(s). But if you have to embe
the client-side name used for the properties in the data object clas
anyway, via an attribute, then the question that is begged _there
becomes: why rename the property at all, if it is going to cause such
headache and require this additional complexity

If you have a concise-but-complete code example that clearly illustrate
the relationships between your classes here, that might help. If you ca
include a link to one or more of the examples you referred to in whic
"developers are usin
expression trees to make refactoring and reflection go hand-in-hand", tha
might help too. I am not really sure what you mean there

Pete

Previous Posts In This Thread:

Re: Refactor-safe Property Access Using Reflection?
How tied to the original data object is your decorator? Do you _have_ t
use reflection? Or is that a convenience, so that you do not have t
explicitly type mappings between strings and actual properties

If the latter, then it seems to me that one alternative would be to giv
up on the convenience (which is costing you in reflection overhea
anyway), and just do the explicit mapping. It could even be as simple a
a big switch (which the compiler will translate into something efficien
anyway). Then, since your decorator is explicitly calling named member
of the decorated class, refactoring catches it

If you are trying to use the same decorator class for all decorated types
and thus reflection is more of a necessity than a convenience, then
do not see an easy way around that. If your decorated types can change an
you do not want to have to go back and fix up all the string-base
accessors through decorators, it seems to me you will have to provide for
separate mechanism to do the mapping. Either strictly string-based, whic
provides zero tie-in to the refactoring tools, or something that _is
inherently tied to the named members of the decorated classes, in whic
case it begs the question: if you have to tie something to the decorated
class, why not just make that the decorator itself?

I suppose yet another alternative would be to use a custom code attribute
to mark the properties with the mapped name(s). But if you have to embed
the client-side name used for the properties in the data object class
anyway, via an attribute, then the question that is begged _there_
becomes: why rename the property at all, if it is going to cause such a
headache and require this additional complexity?

If you have a concise-but-complete code example that clearly illustrates
the relationships between your classes here, that might help. If you can
include a link to one or more of the examples you referred to in which
"developers are using
expression trees to make refactoring and reflection go hand-in-hand", that
might help too. I am not really sure what you mean there.

Pete

Re: Refactor-safe Property Access Using Reflection?
Hi Travis,

If I understand your requirement correctly, instead embedding the string
directly in code, you need to pass your method with your property name.
I am not sure whether it can be done using Expression Tree or not, but it
can be done using reflection.

Just declare your PropertyInfo object on your class,

private static PropertyInfo[] properties = typeof(MyObject).GetProperties();

Then, pass the properties[0].Name to your SetValue method.
Take note that the array is indexed base on how you arrange your
properties.

Regards.

Re: Refactor-safe Property Access Using Reflection?
I am just find below article a nice read.

http://michaelsync.net/2009/04/09/silverlightwpf-implementing-propertychanged-with-expression-tree

Refactor-safe Property Access Using Reflection?
Hello:

I have been seeing a lot of cool examples where developers are using
expression trees to make refactoring and reflection go hand-in-hand. I
am wondering if a trick like that could be performed with properties.
I do not have much first-hand experience with expression trees.

In my system, we have GUI and non-GUI applications. I have a service
layer that returns data objects. When I attach my data objects to a
Windows Form, I decorate them to support INotifyPropertyChanged. The
decorator has methods for getting and setting property values of the
decorated data object.

I have a method that looks like this:

void SetValue<T>(string propertyName, T value) { ... }

This method goes into the decorated data object and sets it is
property. It then raises a PropertyChanged event (passing the property
name).

Now say I change my data object's property names. With the
implementation above, my decorator throws an exception because the
property cannot be found (because it is referring to the old name).

I was hoping to alleviate this by replacing my string with something
spiffy. I was wondering if anyone could think of a way to do it. We're
dealing with a user interface here, so performance is not that
important.

Thanks,
Travis

Re: Refactor-safe Property Access Using Reflection?
wrote:
to =A0
=A0
=A0
as =A0
=A0
s =A0
, =A0
and =A0
=A0
ich =A0
=A0
=A0
=A0
ed =A0
=A0
=A0
an =A0
=A0
t =A0

Yes. I have thought about calling the the underlying methods
explicitly and have allowed it to be done (raising PropertyChanged

Re: Refactor-safe Property Access Using Reflection?
Ah. Now that is what I am talking about! So it could be done using an
expression tree. I am going to have to seriously look into this nifty
little feature.

All it costs is a delegate call. (p =3D> p.Name)

That is an awesome article. I am going to go play around for a while.


Submitted via EggHeadCafe - Software Developer Portal of Choice
Free Online Courses Available for Eggheadcafe.com Users
http://www.eggheadcafe.com/tutorial...8-fc3cf6855293/free-online-courses-avail.aspx
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top