I want to store some backing fields of Properties declared in derived classes in protected Hashtable contained in base class. The usage of this mechanism in derived classes has to beas simple as possible.
So, can I use MethodBase.GetCurrentMethod()
to provide information about calling property (getter - properties are read-only), so it can be recognized as the one and only property that has access to this particular backing field?
EDIT:
Basically, I want to implement pattern:
private SomeClass _someProperty = null;
private SomeClass SomeProperty
{
if (_someProperty == null)
{
_someProperty = new SomeClass();
}
return _someProperty;
}
to look something like this:
private SomeClass SomeProperty
{
return GetProperty(delegate
{
var someProperty = new SomeClass();
return someProperty;
};
}
And in base class
private System.Collections.Hashtable _propertyFields = new System.Collections.Hashtable();
protected T GetProperty<T>(ConstructorDelegate<T> constructorBody)
{
var method = new System.Diagnostics.StackFrame(1).GetMethod();
if (!_propertyFields.ContainsKey(method))
{
var propertyObject = constructorBody.Invoke();
_propertyFields.Add(method, propertyObject);
}
return (T)_propertyFields[method];
}
protected delegate T ConstructorDelegate<T>();
The reason I want to do this is to simplify the usage of properties. I use private properties to create some objects and use them around the class. But when I store their backing fields in the same class, I have the same access to them as to the properties, so I (means user who would create some derived classes in the future) could accidently use backing field instead of the property, so I wanted to restrict access to backing field, while allow to create object and use it.
I tried to use ObsoleteAttribute on the backing fields like this:
[Obsolete("Don't use this field. Please use corresponding property instead.")]
private SomeClass __someProperty;
private SomeClass _someProperty
{
#pragma warning disable 0618 //Disable Obsolete warning for property usage.
get
{
if (__someProperty== null)
{
__someProperty = new SomeClass();
}
return __someProperty ;
}
#pragma warning restore 0618 //Restore Obsolete warning for rest of the code.
}
But, firstly, I cannot force the user to use this pattern, and secondly, it's to much code to write in derived class, which, as I metioned above, I want to be as simple as possible.
Neither
MethodBase
norMemberInfo
do not properly overridesEquals
andGetHashCode
functions, but uses defaultRuntimeHelpers.GetHashCode
andRuntimeHelpers.Equals
. So you will only be able to compare same instance, but not same content. In most cases this will be enough as runtime caches that instances to reuse them. But there is no guarantee this will work stable.As you working with metadata, use something that will identify it uniquely. For example,
MemberInfo.MetadataToken
. You could write your own comparer and use it inside hashtable:It not a good idea to restrict access via reflection to some members as other trusted code can use reflection to access other private data outflanking your checks. Consider restrict access via redesigning your classes.
Also take a look at Code Access Security.
Update according to your edit.
You told your properties are read-only. I guess, simply declaring them as
readonly
is not your option. Looks like you want delayed initialization for properties values. In that case you will not able to declare them asreadonly
. Right?Or maybe you can?
Take a look at
Lazy<T>
class. It's not available in dotnet 2.0, but you can easily implement it or even take any existing implementation (just replaceFunc<T>
with your delegate). Example usage:Pros:
It's a lazy initialization as you wish. Let's test it:
Output will be something like this:
Note, value initialized on first access and not changed later.
Properties are write-protected by a compiler -
_bar
field isreadonly
and you have no access to internal fields ofLazy<T>
. So, no any accidental backing field usage. If you try you will get compilation error on type mismatch:And even if you access it via
this._bar.Value
, nothing terrible would happen and you will get a correct value as if you access it viathis.Bar
property.It is much more simpler, faster and easier to read and maintain.
Thread safety out of the box.
Cons: — (I didn't found)
Few cents about your
hashtable
-based design: