Restricting Access to Properties in NHibernate

Update: unlike what I always thought, "protected internal" means "protected" OR "internal", so this technique is really not that necessary. Thanks to all the commenters who brought that to my attention!

One common requirement is that internal properties of a class can be accessed from other classes on the same assembly. Using NHibernate, you generally cannot use private or internal properties, unless you don’t need to use lazy loading. That is because the NHibernate proxy generator creates dynamically a class for each of your lazy entities, and it does this by subclassing them. The generated classes exist in another assembly, and private and internal properties cannot be accessed from outside the class/assembly on which they are declared.

One solution for this problem is to use internal interfaces for exposing these properties to the same assembly. Consider this example:

   1: public class MyEntity
   2: {
   3:     public virtual Int32 SensitiveProperty
   4:     {
   5:         get;
   6:         protected set;
   7:     }
   8: }

As you can see, the SensitiveProperty can be publicly read but can only be changed from inside the MyEntity class or one inherited from it.

Let’s introduce an internal interface:

   1: interface ISecureModifiable
   2: {
   3:     Int32 SensitiveProperty
   4:     {
   5:         get;
   6:         set;
   7:     }
   8: }

We need to refactor MyEntity so as to realize this interface:

   1: public class MyEntity
   2: {
   3:     public virtual Int32 SensitiveProperty
   4:     {
   5:         get;
   6:         protected set;
   7:     }
   8:  
   9:     Int32 ISecureModifiable.SensitiveProperty
  10:     {
  11:         get
  12:         {
  13:             return(this.SensitiveProperty);
  14:         }
  15:         set
  16:         {
  17:             this.SensitiveProperty = value;
  18:         }
  19:     }
  20: }

Now, all classes in the same assembly as MyEntity and ISecureModifiable can access the SensitiveProperty property, but no other class can – excluding reflection, of course:

   1: MyEntity e = ...;
   2: ISecureModifiable s = e as ISecureModifiable;
   3: s.SensitiveProperty = 100;

Because the interface ISecureModifiable is internal to the assembly on which it is declared, it won’t even be visible from the outside.

                             

6 Comments

  • Hey, what the problem with protected internal?

  • Internal is only for same assembly

  • http://social.msdn.microsoft.com/forums/en-US/csharplanguage/thread/135f6582-7144-496d-a35b-be9ec90f8332/

  • Have a look at Dave Doknjas' answer in that thread: "protected internal" means "protected" OR "internal".

    If you change the filter on the MSDN documentation linked from that thread to a more recent version, you'll also see: "protected internal: Access is limited to the current assembly or types derived from the containing class."

    Also, return is not a function, so adding parentheses around the returned value is not necessary: "return this.SensitiveProperty;"

    And it might be a good idea to delete the spam comment from "fred".

  • RichardD is absolutely correct. Setting your property as protected internal will make it behave as internal, so you will have access to it anywhere in your assembly and internal - you will be able to override it and use from subclasses (in this context it means that it will be accesible from NH's proxy implementation).

  • Yep, totally right, my fault... I never used protected internal and always assumed it meant protected + internal. This technique is indeed not necessary, I will update the post briefly (I hope).
    Thanks!

Comments have been disabled for this content.