Restricting access of class variable to another single class?

Collapse
This topic is closed.
X
X
 
  • Time
  • Show
Clear All
new posts
  • Danny Tuppeny

    Restricting access of class variable to another single class?

    Hi all,

    The next few paragraphs put my question in context, but feel free to
    skip down to the end if you don't care *why* I need the answer! :)

    *************** *************** **********
    *** Start of long-winded description ***
    *************** *************** **********

    I've got some classes that define a tree structure. When the Parent
    property of an item is changed, it automatically updates the Children list.

    The opposite is also true - if you add an item to a Children list, it's
    parent is automatically updated.

    The way this second part works, is with an event (fired when items are
    added to the list) like this:

    children.Added += delegate(object sender,
    ChildList<T>.Ch ildListEventArg s<T> e) { e.Item.parent = (T)this; };

    Notice the lowercase p in parent. If I change this to a P, then I'll get
    a StackOverflow, because setting the parent, adds to the child list, and
    adding to the child list sets the parent. This works fine, because
    everything is in one class (the tree is a tree of one type).

    Now, I've extended it slightly to support ClassA having children of
    ClassB, and ClassB has a parent of ClassA.

    My problem, is that from within ClassB, when the child list is modified,
    I need to set the parent of ClassA. My current method requires that the
    parentClassB property within ClassA be internal (if I use the public
    property, I'll overflow the stack again). However, it's important people
    (me) don't "accidental ly" use this variable when meaning to use the
    public property (else my magic code won't get called, undermining the
    whole point of me abstracting the tree stuff!).

    *************** *************** **********
    *** End of long-winded description ***
    *************** *************** **********

    So... In short - is there any way to restrict access, like "internal",
    but only to subset of classes within the DLL?

    If not, the only way to make sure my code is used properly, is to move
    ClassA and ClassB into a separate DLL, so only they can set each others
    internal data.

    The problem with that, is that ClassA and ClassB then need to be public,
    and that means anyone can reference my DLL and use my classes, whereas
    if everything is in one, they can be internal classes.


    Are there any solutions? :-(
  • Bruce Wood

    #2
    Re: Restricting access of class variable to another single class?

    > So... In short - is there any way to restrict access, like "internal",[color=blue]
    > but only to subset of classes within the DLL?[/color]

    What you're after is something like the "friend" designation available
    in some other languages. C# doesn't have it, so no.

    That said, one way to at least reduce confusion is to expose the
    internal "set parent without fiddling with parent's child list"
    operation as a method, rather than a property (or, even worse, exposing
    the field directly). For example, you could have:

    public ClassB Parent
    {
    get { return this._parent; }
    set
    {
    SetParent(value );
    ... update parent's children ...
    }
    }

    internal void SetParent(Class B newParent)
    {
    this._parent = newParent;
    }

    Then at least the code within your DLL would know that if it's setting
    Parent it's getting the public version, while to do an internal set
    (with no side effects) it has to call the method, and the difference
    will be more visible (rather than being nothing more than a case
    difference: parent versus Parent).

    Comment

    • Danny Tuppeny

      #3
      Re: Restricting access of class variable to another single class?

      Bruce Wood wrote:[color=blue]
      > That said, one way to at least reduce confusion is to expose the
      > internal "set parent without fiddling with parent's child list"
      > operation as a method, rather than a property (or, even worse, exposing
      > the field directly). For example, you could have:
      >
      > public ClassB Parent
      > {
      > get { return this._parent; }
      > set
      > {
      > SetParent(value );
      > ... update parent's children ...
      > }
      > }
      >
      > internal void SetParent(Class B newParent)
      > {
      > this._parent = newParent;
      > }
      >
      > Then at least the code within your DLL would know that if it's setting
      > Parent it's getting the public version, while to do an internal set
      > (with no side effects) it has to call the method, and the difference
      > will be more visible (rather than being nothing more than a case
      > difference: parent versus Parent).[/color]

      I thought about that too (it stops intellisense picking the wrong one
      parent/Parent), though it's not as nice as I'd hoped. I'll go with it
      for now (since it's the best solution), but I think my whole tree thing
      is a bit messy now, so might re-plan it a bit better at some point!

      Comment

      • Anders Norås

        #4
        Re: Restricting access of class variable to another single class?

        You can gain knowledge about who is calling your method by using the StackTrace
        class as shown below.
        StackTrace stackTrace = new StackTrace();
        StackFrame stackFrame = stackTrace.GetF rame(1);
        MethodBase methodBase = stackFrame.GetM ethod();
        Type callingType=met hodBase.Declari ngType;

        stackTrace.GetF rame(1) gets the immediate caller of your method. You can
        then get the type declaring the method that made the invocation by inspecting
        the DeclaringType property of the MethodBase class. You can use this information
        to restrict calls to a method by type.

        A word of caution is due; inspecting the stack trace can be slow.

        Anders Norås



        Comment

        • Bruce Wood

          #5
          Re: Restricting access of class variable to another single class?

          Incidentally, that's why I started using the _xxx notation for private
          member fields. I hate stupid prefixes, but boy, does it make it easier
          to use Intellisense. No more picking the field instead of the property,
          or vice versa.

          It also has the advantage that you see the fields first in the
          debugger's Local window, so you avoid the endless slow scrolling as the
          debugger evaluates all of the properties from A to O just to get to the
          "parent" field.

          Comment

          • Danny Tuppeny

            #6
            Re: Restricting access of class variable to another single class?

            Bruce Wood wrote:[color=blue]
            > Incidentally, that's why I started using the _xxx notation for private
            > member fields. I hate stupid prefixes, but boy, does it make it easier
            > to use Intellisense. No more picking the field instead of the property,
            > or vice versa.
            >
            > It also has the advantage that you see the fields first in the
            > debugger's Local window, so you avoid the endless slow scrolling as the
            > debugger evaluates all of the properties from A to O just to get to the
            > "parent" field.[/color]

            heh, I've used _xxx a few times, but it's so ugly, I always go back to
            lower-case for fields and ProperCase(!) for properties. An addition to
            your reasons, my reason was so that in a method with its own local
            variables, it's easy to distinguish what's "object-scoped", and won't
            disappear when this method ends! :)

            Comment

            • Danny Tuppeny

              #7
              Re: Restricting access of class variable to another single class?

              Anders Norås wrote:[color=blue]
              > You can gain knowledge about who is calling your method by using the
              > StackTrace class as shown below.[/color]
              <snip>

              I thought about that (after the response in the EventHandling thread),
              but it's a little nasty. I think I'll use a method to set it for now, so
              it's not going to slow things down, or leave an ugly field visible
              externally!

              Comment

              Working...