Custom Attribute to Ensure Encapsulation
I'm beginning to look into custom attributes, and I've come up with the following idea: what if I could make an attribute which would restrict the use of a variable to the property it backed?
[RestrictToProperty("Foo")]
private object _foo;
public object Foo
{
get { return _foo; }
set
{
_foo = value;
OnFooChanged(EventArgs.Empty);
}
}
public object NotFoo
{
get { return _foo; } // Warning
set { _foo = value; } // Warning
}
public void Bar()
{
_foo = new object(); // Warning
}
// Warning: 'MyClass._foo' should not be used outside of property 'Foo'
I believe it's possible, because Obsolete
does a similar thing.
[Obsolete]
private object _foo;
public void Bar()
{
开发者_高级运维 _foo = new object(); // Warning: 'MyClass._foo' is obsolete
}
Unfortunately, I have no idea how to go about it, and can't find much beyond simple runtime attribute tutorials. Is this possible? If so, where would I start?
No, that is not possible. ObsoleteAttribute
has a special mention in the C# specification regarding how the compiler itself responds to it.
You could implicity restrict a variables use to a single property by using auto implemented properties.
public class Test
{
public object Foo { get; set; }
}
Edit: If you wanted special logic handled independently in the getter and setter you could try the following code. This seems awfully obnoxious to me though.
public class Test
{
private PrivateMembers Members { get; set; }
public object Foo
{
get
{
return Members.Foo;
}
set
{
Members.Foo = value;
// Do something else here.
}
}
private class PrivateMembers
{
public object Foo { get; set; }
}
}
You should be able to write an FxCop rule that would make this either an error or a warning.
Unfortunately this isn't possible. You might want to explore PostSharp though, which is an Aspect-Oriented IL-weaver for .NET--basically it lets your source-code go through an extra layer of compilation which can inject all the extra ceremony.
Slightly off-topic but you could (ab)use the Obsolete
attribute to achieve what you need.
Mark the backing field as obsolete so that the compiler generates a warning when you try to access it, and then suppress those warnings within the property getter/setter. (The relevant warnings are CS0612 and CS0618.)
[Obsolete("Backing field should not be used outside of property")]
private object _foo;
public object Foo
{
#pragma warning disable 612, 618
get { return _foo; }
set
{
_foo = value;
OnFooChanged(EventArgs.Empty);
}
#pragma warning restore 612, 618
}
This does feel like a nasty hack, and really isn't something that I'd recommend. There are other, preferable alternatives. For example, custom FxCop rules, unit tests, good code commenting etc.
精彩评论