使用属性进行通用约束

时间:2010-11-10 16:32:56

标签: c# generics attributes extension-methods

给出一个例如..

public interface IInterface { }

public static void Insert<T>(this IList<T> list, IList<T> items) where T : IInterface
{
 // ... logic
}

这很好用,但我想知道是否可以使用Attribute作为约束。比如...

class InsertableAttribute : Attribute

public static void Insert<T>(this IList<T> list, IList<T> items) where T : [Insertable]
{
 // ... logic
}

显然这种语法不起作用,或者我不会发布问题。但我只是好奇是否可能,以及如何做到这一点。

3 个答案:

答案 0 :(得分:12)

否。您只能使用(基础)类和接口作为约束。

你可以这样做:

public static void Insert<T>(this IList<T> list, IList<T> items)
{
    var attributes = typeof(T).GetCustomAttributes(typeof(InsertableAttribute), true);

    if (attributes.Length == 0)
        throw new ArgumentException("T does not have attribute InsertableAttribute");

    /// Logic.
}

答案 1 :(得分:7)

没有。您只能使用类,接口,classstructnew()和其他类型参数作为约束。

如果InsertableAttribute指定[System.AttributeUsage(Inherited=true)],那么您可以创建一个虚拟类,如:

[InsertableAttribute]
public class HasInsertableAttribute {}

然后约束你的方法,如:

public static void Insert<T>(this IList<T> list, IList<T> items) where T : HasInsertableAttribute
{
}

然后T将始终具有该属性,即使它仅来自基类。实现类可以通过在自身上指定它来“覆盖”该属性。

答案 2 :(得分:-1)

不,你不能。您的问题不是属性,而是面向对象的设计。请阅读以下内容以了解有关generic type constraint的更多信息。

我建议您执行以下操作:

public interface IInsertable {
    void Insert();
}

public class Customer : IInsertable {
    public void Insert() {
        // TODO: Place your code for insertion here...
    }
}

因此,我们的想法是拥有一个IInsertable接口,并在您希望可插入时在类中实现此接口。这样,您将自动限制可插入元素的插入。

这是一种更灵活的方法,它可以让您轻松地将任何相同或不同的信息从实体持久存储到另一个实体,因为您必须自己在类中实现该接口。