Can Attributes have functionality/behavior or are they simply containers for metadata?

This is something I’ve been wondering for a while, but I’ve got a specific case I’m working with right now that is dealing with this issue. Basically, what are the pros and cons of having custom logic contained in an attribute rather than just having the attribute be a container for data?

So I have a series of enum values that are all decorated with custom attribute(s) that allow the things that these enums represent to be handled through a single stream of logic that recognizes these attributes rather than having all of this logic spread across a number of classes. One of the things that need to be specified is some additional logic for a select few of these enums. The logic itself is not super complicated, and because the majority doesn’t need it, I’d prefer to use attributes to decorate the few enums that do need it and leave the rest as is.

The question I have is whether this logic can be contained within the attribute itself, or whether the attribute should just contain the metadata needed and have the logic specified in another class.

Scenario 1

public enum MyEnum{

Value1,

[MyFilterLogic]

Value2

}

public MyFilterLogicAttribute : Attribute{

public bool Filter(object objToFilter){

/// custom filter logic here…

}

}

Scenario 2

public enum MyEnum {

Value1,

[Filter(typeof(MyFilterLogic))]

Value2

}

public FilterAttribute {

public Type FilterLogicType {get; set;}

}

public IFilterLogic {

bool Filter(object objToFilter);

}

public MyFilterLogic : IFilterLogic {

public bool Filter(object objToFilter){

// custom filter logic here…

}

}

In both cases, the consuming classes know to look for an attribute that could represent a filter. In the first case, the consuming class would get the attribute then be able to call that logic directly. In the second case, the consuming class would get the attribute, then use the type it exposes to instantiate the type, and then call the Filter method.

In my research, I haven’t found anything that says Scenario 1 is not recommended or frowned upon for various reasons, but I also haven’t seen any implemenations or examples like this either. Not that there’s anything directly wrong with Scenario 2, it just seems like an extra step of specifying the type, having the interface, and having to create an instance.

Any thoughts one way or another?

  • on mobile, so apologies on the code formatting

submitted by /u/ThereKanBOnly1
[link] [comments]

Leave a Reply