views:

45

answers:

2

I'm contributing to a library called Fasterflect whose purpose is "improving the developer experience of using reflection". As such, it provides an abstraction built on top of classic reflection and would be used in exactly the same scenarios.

The following shows the current syntax for accessing members via an object instance:

obj.SetPropertyValue( "PropertyWithPrivateSetter", "foo" );
obj.SetFieldValue( "_readOnlyIntegerProperty", 123 );

One user has suggested that we add support for lamdba-based access (similar to Fluent Hibernate):

obj.SetPropertyValue<MyClass>( x => x.PropertyWithPrivateSetter, "foo" );
obj.SetFieldValue<MyClass>( x => x.ReadOnlyInteger, Access.CamelCaseField(Prefix.Underscore), 123 );

I'm having a hard time thinking of scenarios where this would be useful, given that reflection is usually performed on types that you do not know about at compile-time. Am I just lacking in imagination? Are there valid scenarios for reflection where you know the type at compile-time?

There is some additional context for the original suggestion at this NBuilder feature request and you can also view the Fasterflect feature request.

+3  A: 

The main usage scenario would be the one you describe: A property with a public getter, but private setter. By using lambda expressions, you provide compile time checking of the property name (ie: no magic strings), but still provide a way to set a "read only" property via reflection.

Reed Copsey
I can see that that this might be a valid use case. However, what I'm looking for is something that will help me decide whether the suggested syntax is an improvement. Would you consider the second example to be better than the first? Is reflecting on a type that you know at compile-time a common scenario?
Morten Mertner
@Morten: For this specific use case, it's an improvement. The advantage of this over the original syntax is that strings aren't required. This means, for example, that a refactoring where you rename the variable won't break the code. In addition, this will still work post-obfuscation, wheras using strings would "break" during the obfuscation process.
Reed Copsey
Good refactoring tools will also update comments and literals, although I agree that for property access it is an improvement. Not convinced of the field syntax though.
Morten Mertner
Any reasonable obfuscator will rename anything private and so would at least break the field access, since the name rule expressed in the fluent API would not be valid (most likely any reflection code using string constants not discovered at runtime would break). As such I'd vote to keep obfuscation out for the moment ;)
Morten Mertner
@Morten: Obfuscation renaming privates doesn't matter in this case. Since you're using expression trees, you can get the name at *runtime*, which means obfuscation still works. I do this currently to implement INotifyPropertyChanged and still allow obfuscation. That's the main advantage, IMO. As for refactoring tools redoing literals - they do, but this is very error prone. You don't always WANT them to rename literals, so it requires manual searching.
Reed Copsey
@Morten: I agree that, for field access, it's fairly useless...
Reed Copsey
@Reed: I agree that it would work for the property access, but the field expression references the property. It seems unreasonable to assume that I can configure an obfuscator to follow the same naming rules as expressed in the example, and as such I would end up with broken code in either case. Am I missing something? :)
Morten Mertner
@Reed: Ah, good news - thanks for all you input!
Morten Mertner
A: 

To extend on what Reed said (who said it more succinctly than what I had typed) one very valid scenario for this is for "read-only factories" which churn out wrappers providing either true read-only contexts or provide set-up of read-only objects and avoid constructor setup (i.e. true sealed classes).

GrayWizardx
Yes, that does indeed sound like a possible use case for it.
Morten Mertner