0

Say you have a property in a model that looks like this:

[DataType(DataType.DateTime)]
[DisplayFormat(DataFormatString = "{0:yyyy-MM-dd}", ApplyFormatInEditMode = true)]
public DateTime CreationDate { get; set; }

Could you do something like this:

[ComboAttribute] // Does the same thing as the two attributes above
public DateTime CreationDate { get; set; }

I'm exploring ways to ensure all my DateTime properties have the same set of 4 to 5 attributes. If I have to add or change an attribute, currently I have to use Ctrl + F and make sure I get every instance, which is just asking for trouble.

Is this possible? Is there a better way to get the error-proofing I'm looking for?

Sinjai
  • 1,085
  • 1
  • 15
  • 34
  • Yes, it is possible. You can override the filters that deals with this type of attributes and write your own implementation...but...yeah...horrible idea. – marcoaoteixeira Jun 19 '17 at 14:39
  • 1
  • @HimBromBeere If I knew where to start, I would try it myself. – Sinjai Jun 19 '17 at 14:45
  • @Sinjai Yes, that's very easy: `[AttributeUsage(AttributeTargets.Property)] public class ComboAttribute : Attribute { }`. Done. What's it for? – 15ee8f99-57ff-4f92-890c-b56153 Jun 19 '17 at 14:45
  • @EdPlunkett Unless I'm missing something, your code just notes you can make custom attributes, which I know. What I don't know is how you would make it have the effect of several attributes. A custom version of one attribute could simply call the base constructor, but two? It would be used for ensuring several properties that are supposed to have the same 4 or 5 attributes really do. Something like [this](https://stackoverflow.com/questions/2051065/check-if-property-has-attribute) would be good, but what if you want to modify all of those at once? You'd have to recheck and copy/paste. – Sinjai Jun 19 '17 at 14:56
  • @Sinjai Oh, OK. If that's what you want to know, you should say so in your question. All you asked was "Could you do something like this: `[ComboAttribute]`". – 15ee8f99-57ff-4f92-890c-b56153 Jun 19 '17 at 14:58
  • @EdPlunkett Sorry, I thought the implication was clear. Edited. – Sinjai Jun 19 '17 at 14:59

2 Answers2

1

Attributes are data structures attached a type or member definition. At runtime, components can use reflection APIs to find out the attributes which have been applied to a type or member and adjust their behaviour accordingly.

It's important to understand that attributes themselves don't do anything. There always has to be a piece of code looking for that specific attribute. If you define a new attribute, the code will not find it unless it is looking for attributes matching a specific convention or inheriting from a special base type. You need to understand the code looking for the attributes in order to understand whether you can create your own.

For your specific task of creating an aggregation of attributes, the only thing that can work is a pre-processor (such as PostSharp) that can take your custom attribute and literally re-write the code as though you had put the two attributes there.

If you do go down the PostSharp route, there's an example of generating attributes using custom attributes right here: How to inject an attribute using a PostSharp attribute?

Paul Turner
  • 38,949
  • 15
  • 102
  • 166
  • Thanks for taking the time to answer my question before it gets downvoted to oblivion. [This answer](https://stackoverflow.com/a/44634101) seems to say that it can be done, contrary to your answer. Can you take a look? – Sinjai Jun 19 '17 at 16:56
  • Thanks, Paul, for your response to the answer mentioned in the above comment. I've marked yours as the answer. – Sinjai Jun 20 '17 at 00:43
-1

You have two issues here: one, that your attribute will be looked up by whatever framework is expecting it (e.g. MVC is expecting some attributes on properties). Two, that your attribute will perform the logic of all attributes combined.

For the first problem, your attribute will have to inherit from known base attributes, like ValidationAttribute, or implement a known interface, like IActionFilter, depending on what attributes you want to replace.

For the second problem, your attribute can instantiate an instance of each attribute it is replacing, and delegate the functionality it inherited/implemented to the appropriate attribute instance.

mason
  • 31,774
  • 10
  • 77
  • 121
Tsahi Asher
  • 1,767
  • 15
  • 28
  • I don't suppose code examples would be too much to ask for? – Sinjai Jun 19 '17 at 15:18
  • 1
    This approach could work, if all the attributes were implementations of interfaces the components were looking for. Unfortunately the two cited attributes are concrete classes with no possibility of combining into a single implementation. – Paul Turner Jun 19 '17 at 21:07