Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Type constraints in Attributes

I want to write my enum with custom attributes, for example:

public enum SomeEnum: long
{
    [SomeAttribute<MyClass1>]
    Sms = 1,
    [SomeAttribute<MyClass2>]
    Email = 2
}

but attributes doesn't support generics. Well, the most similar solution is:

public enum SomeEnum: long
{
    [SomeAttribute(typeof(MyClass1))]
    Sms = 1,
    [SomeAttribute(typeof(MyClass2))]
    Email = 2
}

And here is problem: I want Class1 to be inherited from ICustomInterface, so with generics I can write constraint:

[AttributeUsage(AttributeTargets.All)]
class SomeAttribute<T> : Attribute where T: ICustomInterface
{
}

but attributes doesn't support generics.

so finally question is: how can I check in compile time (like T constraints) that type is implementing some interface?

like image 814
Alex Zhukovskiy Avatar asked Oct 23 '14 05:10

Alex Zhukovskiy


People also ask

What are type constraints?

A type constraint on a generic type parameter indicates a requirement that a type must fulfill in order to be accepted as a type argument for that type parameter. (For example, it might have to be a given class type or a subtype of that class type, or it might have to implement a given interface.)

What are constraints on attributes?

Attributes can have constraints associated with them, which typically indicate such things as maximum value, minimum value and length of field. You define these constraints on the Properties window for attributes.

What is a type constraint C#?

C# allows you to use constraints to restrict client code to specify certain types while instantiating generic types. It will give a compile-time error if you try to instantiate a generic type using a type that is not allowed by the specified constraints.

What is a type parameter in C#?

The type parameter is a placeholder for a specific type that the client specifies when they create an instance of the generic type. A generic class cannot be used as-is because it is simply a blueprint for that type.


2 Answers

Very simple to your final question:

so finally question is: how can I check in compile time (like T constraints) that type is implementing some interface?

You can not do that.

But you can check it at runtime, with some reflection methods like: Type.IsAssignableFrom

like image 151
BendEg Avatar answered Nov 05 '22 18:11

BendEg


While i've had similar problems you won't get compile time checking for this.

For now this:

public class SomeAttribute : Attribute
{
    public SomeAttribute(Type given)
    {
        Given = given;
        Required = typeof (INotifyDataErrorInfo);
    }

    public Type Given { get; set; }
    public Type Required { get; set; }

    public bool Valid()
    {
        return Required.IsAssignableFrom(Given);
    }
}

public enum TestEnum 
{
    [Some(typeof(string))]
    Sms = 1,
    [Some(typeof(string))]
    Email = 2
}

Is far as you're gonna get sadly.

Though as far as i can recall, if you use PostSharp there is a way to invoke code dependant compile time checks if that's what you're after. That may not point out flaws visually in your IDE, but it still ensures that other devs have to ensure that a certain type is passed.

like image 29
Dbl Avatar answered Nov 05 '22 18:11

Dbl