Roi Shabtai
Roi Shabtai

Reputation: 3085

C# Attributes: One Attribute to Rule Them All?

Is it possible to assign an attribute on a property and use it in order to assign other attributes - doing so without using reflection?

The code:

public class CashierOut : BaseActivity
{
    [Description("Flag indicates whether break to execution.")]
    [DefaultValue(false)]
    [MyCustomAttribute(ParameterGroups.Extended)]
    public bool CancelExecution { get; set; }

    [Description("Flag indicates whether allow exit before declation.")]
    [DefaultValue(true)]
    [MyCustomAttribute(ParameterGroups.Extended)]
    [DisplayName("Exit before declaration?")]
    public bool AllowExitBeforeDeclare { get; set; }
}

I would like to do something like this:

public class CashierOut : BaseActivity
{
    [MyResourceCustom("CashierOut.CancelExecution")]
    public bool CancelExecution { get; set; }

    [MyResourceCustom("CashierOut.AllowExitBeforeDeclare")]
    public bool AllowExitBeforeDeclare { get; set; }
}

public sealed class MyResourceCustom : Attribute
{
    public string ResourcePath { get; private set; }

    public ParameterGroupAttribute(string resourcePath)
    {
        ResourcePath = resourcePath;

        // Get attributes attributes value from external resource using the path.
    }
}

Upvotes: 6

Views: 330

Answers (3)

Andreas
Andreas

Reputation: 6475

You could add a member to MyResourceCustom that wraps Description, DefaultValue, and MyCustomAttribute in an immutable instance (maybe even a static global, if it can be the same for everyone).

public class MyResourceCustom : Attribute {
  public MyResourceCustomDescriptor Descriptor { get; private set; }
  public MyResourceCustom(MyResourceCustomDescriptor descriptor)
  : base() {
    Descriptor = descriptor;
  }

public class MyResourceCustomDescriptor {
  public string          Description    { get; private set; }
  public bool            DefaultValue   { get; private set; }
  public ParameterGroups ParameterGroup { get; private set; }

  public MyResourceCustomDescriptor(string path) {
    // read from path
  }
}

public class MyAdvancedResouceCustomDescriptor : MyResourceCustomDescriptor {
  public string DisplayName { get; private set; }
  // etc...
}

When you fetch the attribute you can get its Descriptor property and read the values.

As a sidenote, you should name it IsDefaultValue.

Upvotes: 1

Huusom
Huusom

Reputation: 5912

Look into Aspect Oriented Programming. You can use tools like postsharp to modify your code either at compile or runtime.

Upvotes: 2

Oded
Oded

Reputation: 499352

Attributes simply add meta data to the members they are defined on - by themselves they do nothing.

You will have to use reflection in order to produce some behaviour depending on the attribute values.

This is how all attributes work - some of the tooling is aware of some attributes (like the compiler and the ConditionalAttribute), but this is still done via reflection.

Upvotes: 6

Related Questions