Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Enforcing type of attribute parameter

Tags:

c#

attributes

Is there a way to enforce that a type parameter passed to an attribute implement specific interface?

public interface IExpectedInterface
{
    void InterfaceMethod();
}

public class MyCustomAttribute : Attribute
{
    public MyCustomAttribute(Type classType)
    {
        this.ConfirmAssignedClassType();

        _classType = classType;
    }

    public void SomeMethod<T>() where T : IExpectedInterface, new()
    {
        //var expectedType = Activator.CreateInstance(this._classType) as IExpectedInterface;
        var expectedType = Activator.CreateInstance(typeof(T)) as IExpectedInterface;

        if (expectedType == null)
        {
            // Wrong type

            throw new ArgumentException(string.Format("Wrong type: {0} could not be created or converted to IActionAuthorization", _classType.ToString()));
        }

        // Do something with expectedType

        expectedType.InterfaceMethod();
    }

    private void ConfirmAssignedClassType()
    {
        if (!typeof(IExpectedInterface).IsAssignableFrom(_classType))
        {
            // Wrong type
            // Can we enforce it via language construct

            throw new ArgumentException(string.Format("Wrong type: {0} must implement IExpectedInterface", _classType.ToString()));
        }

        if (this._classType.GetConstructor(Type.EmptyTypes) == null)
        {
            // Wrong type
            // Can we enforce it via language construct

            throw new ArgumentException(string.Format("Wrong type: {0} must have parameter less constructor", _classType.ToString()));
        }
    }

    private Type _classType;
}

public class TestClass
{
    [MyCustom(typeof(TestClassImplementsExpectedInterface))]
    public void TestMethod1()
    {
    }

    [MyCustom(typeof(TestClassDoesntImplementExpectedInterface))]
    public void TestMethod2()
    {
    }
}

public class TestClassImplementsExpectedInterface : IExpectedInterface
{
    public void InterfaceMethod()
    {
        return;
    }
}

public class TestClassDoesntImplementExpectedInterface
{
}
like image 717
amit_g Avatar asked May 27 '11 19:05

amit_g


People also ask

What are attributes What are the required parameters?

An attribute is a variable of any type that is declared directly in a class. A parameter is a variable defined by the function that receives a value when it is called. An attribute is used with classes and objects. A parameter is used with a function or a method.

What are positions and named parameters in attributes?

The positional parameters for an attribute correspond to the parameters passed to the attribute type's public constructors. The named parameters for an attribute correspond to the set of public read-write or write-only instance properties and fields of the attribute type.

What are attributes in C sharp?

In C#, attributes are classes that inherit from the Attribute base class. Any class that inherits from Attribute can be used as a sort of "tag" on other pieces of code. For instance, there is an attribute called ObsoleteAttribute . This is used to signal that code is obsolete and shouldn't be used anymore.

What are attributes in dot net?

Attributes provide a powerful method of associating metadata, or declarative information, with code (assemblies, types, methods, properties, and so forth). After an attribute is associated with a program entity, the attribute can be queried at run time by using a technique called reflection.


1 Answers

Couldn't this be done with generics? (Edited -- cannot create a generic subclass of Attribute)

   public class MyAttribute: Attribute 
    {
        private Type _ClassType;
        public MyAttribute(Type classType)
        {
            _ClassType = classType;
        }
        public void SomeMethod<T>() where T: IMyInterface
        {
            var expectedType = Activator.CreateInstance(typeof(T)) as IMyInterface;
        // Do something with expectedType
        }
    }

And of course the other answer's translation to use "new" makes a lot of sense!

like image 64
Jamie Treworgy Avatar answered Sep 19 '22 15:09

Jamie Treworgy