ReadOnlyBase Constructors - Newbie Question

ReadOnlyBase Constructors - Newbie Question

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


JabbaTheNut posted on Saturday, March 31, 2007

My question is this...

Must I have a private constructor in a ReadOnlyBase object?

I have a SecurityPolicy object that has a couple of validation methods (to verify proper password format, expired passwords, account lockouts, etc.).  Each of these methods returns a SecurityPolicyStatus object that provides the result of the validation method, as well as a list of any broken policies.  This object is intended for internal consumption and should not be used by the UI.  The SecurityPolicyStatus object is instantiated and populated directly by each of the respective SecurityPolicy object methods, based on data existing inside the SecurityPolicy object.  Consequently, there is no need for any DataPortal methods in the SecurityPolicyStatus object to retrieve data from the database.  Below is the code of my object (please note that Base.LVReadOnlyBase is a subclass of Csla.ReadOnlyBase).  It does not currently have a private constructor.

    [Serializable()]
    internal class SecurityPolicyStatus : Base.LVReadOnlyBase<SecurityPolicyStatus>
    {
        # region Properties

        private Guid _id = Guid.NewGuid();
        private bool _isValid;
        private List<string> _brokenPolicies = new List<string>();

        /// <summary>
        /// Determines whether or not the validation method
        /// passed the required security policies.
        /// </summary>
        internal bool IsValid
        {
            get { return _isValid; }
            set
            {
                _isValid = value;
            }
        }

        /// <summary>
        /// Gets a list of broken security policies.
        /// </summary>
        internal List<string> BrokenPolicies
        {
            get { return _brokenPolicies; }
        }

        # endregion

        #region Business Methods

        /// <summary>
        /// Adds a broken security policy to the <see cref="BrokenPolicies"/> list.
        /// </summary>
        /// <param name="item">
        /// A string describing the security policy that was broken.
        /// </param>
        internal void AddBrokenPolicy(string item)
        {
            _brokenPolicies.Add(item);
        }

        /// <summary>
        /// Returns a unique identifying value for the object.
        /// </summary>
        protected override object GetIdValue()
        {
            return _id;
        }

        #endregion

        #region Constructors

        /// <summary>
        /// Class constructor
        /// </summary>
        internal SecurityPolicyStatus(){ }

        #endregion

    }

The internal constructor is used by the SecurityPolicy object to instantiate the SecurityPolicyStatus object. 

My confusion comes from the ResourceInfo object in the CSLA.Net book (page 448).  It provides both private and internal constructors.  The book states that the private constructor prevents the UI from instantiating the object.  But, doesn't the internal constructor also prevent the UI from instantiating the object?  My assumption is that the business objects are contained within their own assembly, separate from the UI (like the ProjectTracker.Library is).

I realize this is a very basic question and apologize in advance for any offense.  I just want to solidify my understanding before I get too deep and discover that I missed something fundamental that will require recoding.

Thanks for your help.

Bayu replied on Monday, April 02, 2007

Hello,

Maybe the following helps you in your reasoning:
- private constructors are accessible only from within the same class
    - typically they are invoked from a shared (static) factory method
    - the central idea of factory methods paired with private constructors is that your object needs some initalization (e.g. calling dp_create) which you make more explicit in a factory method than with default constructors

- protected constructors are accessible from within the class and from any descendant class
    - you typically use these on abstract classes that do not yet provide factory methods (you expect these to be defined on the concrete subclasses)


Both private and protected members are not accessible from any external object.

There is one caveat of course, and that would be reflection. In the end any member IS accessible (even private ones) through the use of reflection (note for example that the dp_methods are protected, yet the dataportal is able to invoke them through reflection).


HTH
Bayu

ajj3085 replied on Monday, April 02, 2007

Well, the goal is to keep the UI from creating objects via a constructor.  If your business library needs to use a constructor though, its fine to make one internal... but I wouldn't make it public.

OTOH, I always keep my constructors private, instead using internal factory methods for BOs to create other BOs.  There isn't really any technical reason to do this... its more for consistence within the BO library.  Every BO is created by a factory method.

The key though is that yes, your BO should be in its own seperate assembly.  If its in with the UI project, the UI project has access to all the interally marked members as well, and that's what you're trying to prevent.

As far as going with private / protected constructors and internal factory methods, vs. jut having an internal constructor, the choice is up to you.  As long as your consistent, you should be fine.

JoeFallon1 replied on Tuesday, April 03, 2007

One other thing to consider:

Every class in your library does NOT need to derive from CSLA. In this case you are probably better off skipping the inheritance entirely. Now you "stand alone" class is clearly something used internally by the parent class. You can create instances of it and store them, etc.

Joe

 

Copyright (c) Marimer LLC