NibblyPig
NibblyPig

Reputation: 52952

How can I have an [Attribute] that accepts a type in C#?

I created an EvaluateAttribute, and I want it to accept various IEvaluators specified like this:

[Evaluate(CatEvaluator, DogEvaluator)]
public void someMethod()
{
}

Since CatEvaluator and DogEvaluator are types, I set up my attribute class like this:

   public class EvaluateAttribute<T> : Attribute where T:IAccessEvaluator

and constructor:

public EvaluateAttribute(params T [] accessEvaluators)
{
    _accessEvaluators = accessEvaluators;
}

C# doesn't like generics and attributes though, it would seem. Is there a solution to this?

I want my attribute to instantiate each type with CreateInstance and run an evaluate method specific in IAccessEvaluator.

Upvotes: 0

Views: 88

Answers (2)

Rob Levine
Rob Levine

Reputation: 41338

There is nothing to stop the attribute accepting types:

public class EvaluateAttribute : Attribute
{
    private readonly Type[] _accessEvaluators;

    public EvaluateAttribute(params Type[] accessEvaluators)
    {
        _accessEvaluators = accessEvaluators;
    }
}

which you can then use like this:

[Evaluate(typeof(CatEvaluator), typeof(DogEvaluator)]
public void someMethod()
{

}

Unfortunately, you lose the type safety - but you could always add some run-time checking to the attribute's constructor. Something along the lines of:

public EvaluateAttribute(params Type[] accessEvaluators)
{
    foreach (var type in accessEvaluators)
    {
        if (!typeof(IAccessEvaluator).IsAssignableFrom(type))
        {
            throw new InvalidOperationException("Suppied type must be of type IAccessEvaluator");
        }
    }
    _accessEvaluators = accessEvaluators;
}

Upvotes: 1

Matten
Matten

Reputation: 17603

You probably don't need to use generics if you just want to pass classes implementing IAccessEvaluator. Just change the signature to

public EvaluateAttribute(params IAccessEvaluator [] accessEvaluators)
{
    _accessEvaluators = accessEvaluators;
}

Reread your question. You're using types like objects, so my first impression was to write the above answer. If you need to annotate types, you should have a look at the comment on your question (by MUG4N).

public EvaluateAttribute(params Type [] accessEvaluators)
{
    _accessEvaluators = accessEvaluators;
}

[Evaluate(typeof(CatEvaluator), typeof(DogEvaluator)]
public SomeClass{ }

and change _accessEvaluators to Type[]

Upvotes: 1

Related Questions