Подтвердить что ты не робот

Использование атрибутов для общих ограничений

Для примера, например..

public interface IInterface { }

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

Это отлично работает, но мне было интересно, можно ли использовать атрибут в качестве ограничения. Такие, как...

class InsertableAttribute : Attribute

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

Очевидно, что этот синтаксис не работает, или я не буду публиковать вопрос. Но мне просто интересно, если это возможно или нет, и как это сделать.

4b9b3361

Ответ 1

Нет. Вы можете использовать (базовые) классы и интерфейсы в качестве ограничений.

Однако вы можете сделать что-то вроде этого:

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

Ответ 2

Нет. Вы можете использовать только классы, интерфейсы, class, struct, new() и другие параметры типа в качестве ограничений.

Если 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 всегда будет иметь атрибут, даже если он исходил только из базового класса. Реализация классов могла бы "переопределить" этот атрибут, указав его сами.

Ответ 3

Нет, вы не можете. Ваш вопрос касается не атрибутов, а объектно-ориентированного дизайна. Пожалуйста, прочитайте следующее, чтобы узнать больше о generic type constraint.

Я предлагаю вам сделать следующее:

public interface IInsertable {
    void Insert();
}

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

Итак, идея состоит в том, чтобы иметь интерфейс IInsertable и реализует этот интерфейс внутри класса всякий раз, когда вы хотите быть вставленным. Таким образом, вы автоматически ограничиваете вставку для вставленных элементов.

Это более гибкий подход, и он даст вам легкость сохранить любую ту же или другую информацию от объекта к другой, поскольку вы должны реализовать интерфейс самостоятельно в своем классе.