0

ex.

[NoZero()]
public int Quantity{ get; set; }

Basically, I don't want the Quantity to be set to less than zero.

h3n
  • 5,142
  • 9
  • 46
  • 76
  • 4
    Attributes do nothing by itself, they just declare something. You can create any attribute and call it like you want, for example `[NonNegative]`, or you can use existing DataAnnoations attributes. However, you will need to handle the logic of validation somewhere. What you can do with property - you can provide setter which will validate `value` and throw exceptions for invalid values. It depends on your requirements and how \ by whom the property will be assigned. – Yeldar Kurmangaliyev Nov 27 '18 at 16:45
  • 1
    You need more context. Is whatever consumer of the property attribute-aware? – Mike Guthrie Nov 27 '18 at 16:46
  • Why don't you specify a setter that checks the value before storing it? What you ask is *validation*, not overriding. Data annotation attributes are used to specify validation rules that validator classes can use to ensure an object fulfills all of them. They don't override the setters – Panagiotis Kanavos Nov 27 '18 at 16:47
  • Why you don't implement the setter with a simple condition? `private int _quantity; public int Quantity{ get => _quantitiy; set { if(value < 0) throw new Exception(); _quantitiy = value; }` – Kevin Kouketsu Nov 27 '18 at 16:48
  • Range checking is already provided by the [Range](https://learn.microsoft.com/en-us/dotnet/api/system.componentmodel.dataannotations.rangeattribute?view=netframework-4.7.2) data annotation attribute. Data Annotationsa are recognized by every .NET stack (Winforms, WPF, ASP.NET). In [ASP.NET for example](https://learn.microsoft.com/en-us/aspnet/mvc/overview/older-versions/mvc-music-store/mvc-music-store-part-6) they can be used to generate both server and client-side validation code – Panagiotis Kanavos Nov 27 '18 at 16:50
  • This very specific scenario could also be handled by making `Quantity` a `uint`. I don't actually recommend doing this, because `uint` isn't CLS compliant (meaning .NET languages aren't required to be able to handle it, though most do), it won't work for any other validation condition than "must not be negative", and people can just blindly cast values to get around errors rather than check what they're doing... but just for completeness. – Jeroen Mostert Nov 27 '18 at 16:52
  • I was trying to add a constructor to the custom attribute so I can pass the object something like this: NoZero(this). Is there a way to pass the object to the attribute constructor? – h3n Nov 27 '18 at 17:17
  • You should carefully re read the first comment. Yes you can pass args to an attribute....but it wont do what you think it will – Ňɏssa Pøngjǣrdenlarp Nov 27 '18 at 17:22
  • You could create a Utility class with a generic static setter method and use that in your properties: `set => PropertyHelper.ValidationSetter(this, "Quantity", value);` but that doesn't seem very clear, and would have to use Reflection which isn't very performant. – NetMage Nov 27 '18 at 18:21

2 Answers2

1

This doesn't answer your question directly, but to offer an interesting alternative.

If you are making use of an IoC framework and one which has the possibilities of "interception" you could force your property access to be intercepted (as long as the class is passed in via IoC off course).

Ninject Intercept any method with certain attribute?

I haven't tried it myself with property access, but in theory it could work.

Or alternatively, using a code-weaving library directly: https://github.com/Fody/Fody this effectively weaves itself into the IL.

Alex KeySmith
  • 16,657
  • 11
  • 74
  • 152
0

The traditional way to do this is

protected int _quantity;

public int Quantity
{
    set
    {
        if (_quantity < 0) throw new ArgumentOutOfRangeException("Some message");
        _quantity = value;
    }
    get
    {
        return _quantity;
    }
}

You can't really do it with attributes unless you write code that checks for the attributes before setting the property. This is how DataAnnotation attributes work, for example. In the document, notice the following:

To implement the above requirement we need to code in the UI layer to accommodate/validate the above criteria’s.

So you see, you'd have to write a lot of complicated code, and be careful not to set the property directly. That is why most people don't do it with attributes.

John Wu
  • 50,556
  • 8
  • 44
  • 80
  • I think everyone knows how to override the setter this way. What I need is a way to intercept the value by way of a custom attribute. @yeldar has a good point on attributes. – h3n Nov 27 '18 at 17:07