0

I have a dependency graph class built in c# with several private data properties that are supposed to only be accessed, but more importantly modified, through the standard 'getter / setter' methods. I came across a test which exposes the public interface through casting an IEnumerable as an ICollection. I am unsure how to prevent this obviously unwanted action.

Here is the failing unit test that confirms I am exposing private data:

[TestMethod]
    public void PrivateDataTest()
    {
        try
        {
            DependencyGraph dg = new DependencyGraph();
            dg.AddDependency("a", "b");
            dg.AddDependency("a", "c");
            ICollection<string> temp = (ICollection<string>)dg.GetDependents("a");
            temp.Add("d");
            Assert.IsTrue(new HashSet<string> { "b", "c", "d" }.SetEquals(temp));
            Assert.IsTrue(new HashSet<string> { "b", "c" }.SetEquals(dg.GetDependents("a")));
        }
        catch (Exception e)
        {
            if (!(e is NotSupportedException || e is InvalidCastException))
                Assert.Fail();
        }
    }

And here is my method 'GetDependents' which is called simultaneously to the ICollection cast.

/// <summary>
/// Enumerates dependents(s).
/// </summary>
public IEnumerable<string> GetDependents(string s)
    {
        try
        {
            return this.data[s].getDependencies();
        }
        catch (Exception e)
        {
            return new List<string>();
        }
    }

Additionally this is the 'data' property being accessed:

    // key = node name, value = node object and all node data e.g. dependencies, dependees, name
    private SortedDictionary<String, Node> data;

The 'data' property contains a string which represents the node's name e.g. "a", and a custom Node object. The name is the key to the actual Node object, which is a nested class that is used to store a node's name, and list of dependencies / dependees. Here is my my Node class (Note. I stripped away a lot of methods that are irrelevent for the purpose of this question):

public class Node 
    {
        private String name;
        private List<String> dependencies;
        private List<String> dependees;

        /// <summary>
        /// construct a new Node by passing in a name and lists for both the dependencies and the dependees
        /// </summary>
        /// <param name="_name"></param>
        /// <param name="_dependencies"></param>
        /// <param name="_dependees"></param>
        public Node(String _name, List<String> _dependencies, List<String> _dependees)
        {
            name = _name;
            dependencies = _dependencies;
            dependees = _dependees;
        }

        /// <summary>
        /// construct a Node with just a name and blank dependent lists
        /// </summary>
        /// <param name="_name"></param>
        public Node(String _name)
        {
            name = _name;
            dependencies = new List<string>();
            dependees = new List<string>();
        }

        /// <summary>
        /// getter for the dependencies property
        /// </summary>
        public List<String> getDependencies()
        {
            return this.dependencies;
        }
    }

I hope this is enough information for someone to understand the scope of my question as it relates to my graph. I will reiterate; how would one go about preventing this breach of interface via casting? This is my first question on StackOverflow, and I'm also fairly new to the C# language, so I apologize if my formatting / lack of understanding is incorrigible.

goof ball
  • 21
  • 4
  • 1
    possible duplicate of [ReadOnlyCollection or IEnumerable for exposing member collections?](http://stackoverflow.com/questions/491375/readonlycollection-or-ienumerable-for-exposing-member-collections) (More precisely, this question has your answer, although it's not the same question) – Amit Sep 18 '15 at 05:26
  • 1
    You can never prevent breach of interface. calling code can always use reflection to access private member.s – Richard Schneider Sep 18 '15 at 05:35
  • Thanks for the info guys. Guess all that post formatting was wasted energy. Hehe – goof ball Sep 18 '15 at 05:50

0 Answers0