强制执行属性参数类型

时间:2011-05-27 19:22:52

标签: c# attributes

有没有办法强制传递给属性的类型参数实现特定的接口?

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
{
}

4 个答案:

答案 0 :(得分:5)

这不能用泛型来完成吗? (已编辑 - 无法创建属性的通用子类)

   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
        }
    }

当然,另一个答案是使用“new”的翻译很有意义!

答案 1 :(得分:3)

如果由于某种原因你不想搞乱泛型(例如将所有属性放入列表或其他东西),那么可能会考虑稍微更好的方法,尽管仍然没有编译时检查。您可以调用Type.IsAssignableFrom方法,而不是调用Activator.CreateInstance(根据是否存在0-param ctors,可能会也可能不会起作用)(尽管您似乎假设存在0-param ctor,所以这可能有些没有实际意义。)

if (!typeof(SomeInterface).IsAssignableFrom(_ClassType)))
// Throw exception

答案 2 :(得分:2)

您可以将方法转换为通用方法,例如

public class MyAttribute : Attribute
{
    public void SomeMethod<T>() where T : ISomeInterface, new()
    {
        var expectedType = new T();
        // Do something with expectedType
    }
}

new()类型约束意味着该类型必须具有公共的无参数构造函数,这意味着您可以执行new T()。这样就无需使用Activator

请注意,正如Duncan Howe指出的那样,泛型类型无法继承Attribute,因此您无法public class MyAttribute<T> : Attribute

答案 3 :(得分:0)

为什么不通过构造函数(例如Public MyAttribute(IMyInterface myObject))传递对象并将其存储在属性中。然后,如果您需要该类型,请显式调用typeof(myObjectProperty)