Changing from Private to Managed Backing Fields

Changing from Private to Managed Backing Fields

Old forum URL: forums.lhotka.net/forums/t/6383.aspx


Peran posted on Monday, February 09, 2009

I would like to change some BB objects with registered properties from private backing fields to managed backing fields with the least amount of effort!

I would like to canvass option on the following solution:

I start with a registered property using a private backing field

        private static PropertyInfo<string> nameProperty = RegisterProperty(new PropertyInfo<string>("Name"));
        private string name = nameProperty.DefaultValue;

        public string Name
        {
            get
            {
                return GetProperty(nameProperty, this.name);
            }

            set
            {
                SetProperty(nameProperty, ref this.name, value);
            }
        }

and convert the private backing field to a private property which wraps up the ReadProperty & LoadProperty functions.

        private static PropertyInfo<string> nameProperty = RegisterProperty(new PropertyInfo<string>("Name"));

        // replace private backing field with private property
        private string name
        {
            get
            {
                return ReadProperty(nameProperty);
            }

            set
            {
                LoadProperty(nameProperty, value);
            }
        }

        public string Name
        {
            get
            {
                return GetProperty(nameProperty);
            }

            set
            {
                SetProperty(nameProperty, value);
            }
        }

by doing this I now do not need to change any validation rules or data portal code i.e. the following code replacement do *not* need to be done.

Valiadtion Rule

if(ExistsCommand.Exists(target.name))
if(ExistsCommand.Exists(target.ReadProperty(nameProperty)))

DataPortal_Fetch

this.name = dr.GetString("Name")
LoadProperty(nameProperty, dr.GetString("Name"))

DataPortal_Insert

cm.Parameters.AddWithValue("Name", this.name)
cm.Parameters.AddWithValue("Name", ReadProperty(nameProperty))

I also prefer the syntax 'this.name' rather than 'this.ReadProperty(nameProperty)' etc.

I'm sure you have an opinion why I should not do this! but I would be interested in the reasons.


Peran

RockfordLhotka replied on Tuesday, February 10, 2009

If you access a property directly, you trigger any authorization and validation rules in the get/set code.

ReadProperty() bypasses the authz check that occurs in GetProperty() (and thus your get block).

LoadProperty() bypasses the authz and business rules that are run in SetProperty() (and thus in your set block).

You can use the BypassPropertyChecks object to cause GetProperty() and SetProperty() to work like ReadProperty() and LoadProperty():

using (this.BypassPropertyChecks)
{
  var tmp = this.Name;
  this.Name = "value";
}

Obviously if you switch to a managed backing field, you can't access the field directly at all, because the field no longer exists. So you must access either the property, or the managed field through the helper methods.

You do not need to switch to using managed backing fields. They exist primarily to support code in Silverlight (and probably Azure, Compact Framework and other lower trust scenarios in the future). So I think you should consider using managed backing fields, as they'll make your life better in the future - but if you really can't stomach the idea, you don't need to use them.

And even if you stick with private backing fields, you can still use Silverlight, etc. You just need to write OnGetState() and OnSetState() methods in every one of your classes to get/set the private field values into the serialization byte stream. That's a total pain, but it isn't hard code, and if you are using code-gen it is a non-issue.

Peran replied on Wednesday, February 11, 2009

Thanks for the advice, I am switching based on the your recommendations in chapter 7 with automatic serialization for Silverlight in mind.

The ByPassPropertyChecks looks like a good option.


Regards

Peran

daniel_higgins replied on Thursday, February 12, 2009

Hi Peran, I'm not sure that I understand Rocky's response. What you're doing is the same as what I have done, except that instead of using "name" as the private property, I use "_Name". Just like you have suggested, I put calls to ReadProperty and LoadProperty in this private property. My public "Name" property hits GetProperty and SetProperty. It *appears* to work for me.

RockfordLhotka replied on Thursday, February 12, 2009

You can absolutely still use private backing fields. That is totally supported. And it has better performance than managed backing fields.

 

Where you’ll run into trouble is if you try to move to Silverlight (and probably to Azure, Compact Framework or other security-restricted scenarios). The reason is that in those environments reflection is limited or doesn’t work at all. And so in those environments there is no BinaryFormatter or NetDataContractSerializer, nor can one be created.

 

This means there’s no automated way to get at private fields in a class.

 

CSLA .NET for Silverlight includes the MobileFormatter. We wrote this to enable serialization of objects to/from Silverlight. Obviously we did this without using reflection, because that’s not available.

 

If you use managed backing fields, MobileFormatter can do all the work for you – serialization just works.

 

If you use private backing fields, you need to write two methods in every class to help the MobileFormatter. You need to write a method that takes the values from your private fields and puts them into the serialization stream. And you need to write a method that takes the values from the deserialization stream and puts them into your private fields.

 

If you did any VB5 or VB6 you may have worked with the PropertyBag. This is the same model. Or if you’ve ever manually implemented ISerializable in .NET, this is the same model.

 

It is OK to do this – it is just a bunch of boring grunt work, and is the type of code that’s easy to get wrong (add a new field, and forget to update the two methods and you have a hard to find/debug bug).

 

If you never move to Silverlight, Azure or other future technologies, you won’t care. Or if you use code generation you probably don’t care, because your template can generate these methods.

 

Personally I have taken to using managed backing fields, and only fall back to private backing fields if absolutely necessary (which hasn’t actually happened yet).

 

Rocky

daniel_higgins replied on Thursday, February 12, 2009

Hey Rocky,

I really love the managed fields, "like my absolutely favorite recent change". But I think we've been talking about different things. I meant private PROPERTIES that wrap the calls to ReadProperty and LoadProperty -- for use with managed fields. I use resharper live templates to generate these, and it makes it much easier for my little brain to deal with the data access code.

Thanks

Daniel.

RockfordLhotka replied on Thursday, February 12, 2009

Oh, I see.

 

There should be no problem doing that – seems like a good idea to me.

 

Rocky

 

Peran replied on Wednesday, February 18, 2009

Hi Daniel,

It's encouraging to hear that someone else is using the technique :-)


Peran

Copyright (c) Marimer LLC