R4D4
R4D4

Reputation: 1402

How can I return a ReadOnly object class with mutable properties while allowing write access

I've got quite a number of classes, which have got the standard set and get methods. My problem is that many of these set methods should not be callable from outside the class which holds the objects. I'm not quite sure if there are any patterns or C# for lack of a better word - operations that would make this easier.

In reference to the code below, there are a number of classes similar to SecureSite, which the controller should be able to call functions or access variables to modify the SecureSite (and the other similar classes). However when the user asks to see SecureSite etc. they shouldn't be able to change this.

From my limited knowledge and the answers I've seen to similar questions on this site, the main issue appears to be that the Write_SecureSite can't be made fully immutable due to the List<String> AccessHistory variable. So, what I've come up with looks as ugly as a bulldogs backside and is just as messy. Essentially there is a Write version of the SecureSite class which contains a class within it, which returns a readonly version of the SecureSite class.

So, am I missing something magic in C# that would make this all so much easier?

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ReadOnlyExample {


    public class Write_SecureSite {

        private List<String> mAccessHistory;
        public List<String> AccessHistory {
            get {
                return mAccessHistory;
            }
        }
        public SecureSite ReadOnly {
            get {
                return new SecureSite(this);
            }
        }

        public class SecureSite {
            public SecureSite(Write_SecureSite aParent) {
                AccessHistory=aParent.AccessHistory;
            }
            public IEnumerable<String> AccessHistory;
        }

    }


    public static class Controller {

        private static Write_SecureSite SimpleSecureSite=new Write_SecureSite();

        public static Write_SecureSite.SecureSite Login(String MyLogin) {
            SimpleSecureSite.AccessHistory.Add(MyLogin);
            return SimpleSecureSite.ReadOnly;
        }

        public static Write_SecureSite.SecureSite Details() {
            return SimpleSecureSite.ReadOnly;
        }

    }


    public static class User {

        public static void Miscellaneous() {
            Controller.Login("Me");
            Write_SecureSite.SecureSite SecureSite=Controller.Details();

            //Not going to happen.
            SecureSite.AccessHistory.Add("Me2");

            //No problem.
            foreach(String AccessedBy in SecureSite.AccessHistory) {
                Console.Out.WriteLine("Accessed By: "+AccessedBy);
            }

        }

    }


}

Upvotes: 0

Views: 597

Answers (2)

Tab
Tab

Reputation: 1762

This is not so much an answer as a direction to look into. I am also struggling with the Immutable class

So far I am using my constructors to set my read-only private vars I am using methods to update my lists internally instead of exposing them as public properties: ie. use public Void Add(string itemToAdd)

I am reading a book by Petricek and Skeet called "Real World Functional Programming" and it is helping me move in the direction you are discussing

Here is a small tutorial from the same author's that introduces some basic concepts: http://msdn.microsoft.com/en-us/library/hh297108.aspx

Hope this helps a bit

Update: I probably should have been clearer: I was looking to point you in the direction of a more functional view as opposed to rewriting the class you had listed in your question - my apologies (removed sample)

Upvotes: 0

Hubi
Hubi

Reputation: 1629

I suggest to use interfaces:

public interface IReadSecureSite
{
  IEnumerable<String> AccessHistory { get; }
}

class Write_SecureSite : IReadSecureSite
{
    public IList<String> AccessHistoryList { get; private set; }

    public Write_SecureSite()
    {
        AccessHistoryList = new List<string>();
    }

    public IEnumerable<String> AccessHistory {
        get {
            return AccessHistoryList;
        }
    }
 }

 public class Controller
 {
    private Write_SecureSite sec= new Write_SecureSite();

    public IReadSecureSite Login(string user)
    {
       return sec;
     }

 }

 ...
 Controller ctrl = new Controller();
 IReadSecureSite read = ctrl.Login("me");
 foreach(string user in read.AccessHistory)
 {
 }

Upvotes: 1

Related Questions