RelationshipTypes.PrivateField - how to use it?

RelationshipTypes.PrivateField - how to use it?

Old forum URL:

tiago posted on Friday, May 28, 2010

Hi Rocky,

Referring to Beta 2 4.0.0-100524 Change Log

PrivateField relationship type (100519)
Add new PrivateField relationship type to IPropertyInfo so property metadata can know
that a property has a private backing field. This change includes making ReadProperty()
and LoadProperty() automatically get/set these values using reflection.

I suppose this should be used like this

private static PropertyInfo<int> DocTypeIDProperty = RegisterProperty<int>(p => p.DocTypeID, "Doc Type ID", RelationshipTypes.PrivateField);
public int DocTypeID
    get { return GetProperty(DocTypeIDProperty); }
    set { SetProperty(DocTypeIDProperty, value); }

Note the syntax I used up to this change was

public int DocTypeID
    get { return GetProperty(DocTypeIDProperty, _docTypeID); }
    set { SetProperty(DocTypeIDProperty, ref _docTypeID, value); }

I'm wrong and I don't understand how to use this new feature.

RockfordLhotka replied on Friday, May 28, 2010

The PrivateField flag is intended to tell CSLA that you are using a private field. So you do need to use the private field syntax in your property declaration - and now you can tell CSLA that this is what you are doing.

That is important, because it means that the non-generic ReadProperty and LoadProperty methods then know that they should use BypassPropertyChecks and reflection to interact with the property, rather than using the field manager.

In other words, we needed some way (specifically in new business rule system) to be able to get/set properties regardless of whether the property used a managed or private backing field. Managed was easy - this is what managed properties are all about.

But private backing fields are hard, because there's no guaranteed way for CSLA to know how to interact with the field (and in Silverlight it is essentially impossible). If you tell CSLA that you are using a private backing field however, then ReadProperty/LoadProperty can know that the only way to get/set the value is to use BypassPropertyChecks to disable rule processing, and then use reflection to interact with the public property itself.

Now ReadProperty and LoadProperty are still virtual (another CSLA 4 change), so if you want to avoid the use of reflection you can always override the methods and use a switch block or something based on the requested property name to directly get/set the field value. That'll be faster, but obviously less maintainable. That was my original solution to this problem, until Jonny suggested the PrivateField approach as a more maintainable (if somewhat slower) alternative.

So now you really have two choices for solving this problem. The most important thing is to use one of the two, because otherwise you can't really leverage the new rules system when using private backing fields.

tiago replied on Friday, May 28, 2010

Thanks for your reply. I guess the "PrivateField" is useless on Unmanaged properties with type conversion...

RockfordLhotka replied on Friday, May 28, 2010

Why do you say that? Certainly it will impose some limitations, but it will work fine.

If you have a private backing field, the non-generic ReadProperty/LoadProperty methods will use the property to set the value, not the field. So it will use whatever type conversion is in the property (like SetPropertyConvert) automatically.

If you don't want that to occur, then you'd need to override LoadProperty so you can write your own code to directly set the private field.

In other words, you can let CSLA set the property - and use whatever type conversion is already in place - or you can override the methods to set the field directly, presumably to avoid type conversion.

Copyright (c) Marimer LLC