开发者

Custom Attribute to Ensure Encapsulation

开发者 https://www.devze.com 2023-01-06 05:48 出处:网络
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?

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.

0

精彩评论

暂无评论...
验证码 换一张
取 消