Использование атрибутов для общих ограничений
Для примера, например..
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
}
Очевидно, что этот синтаксис не работает, или я не буду публиковать вопрос. Но мне просто интересно, если это возможно или нет, и как это сделать.
Ответы
Ответ 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
и реализует этот интерфейс внутри класса всякий раз, когда вы хотите быть вставленным. Таким образом, вы автоматически ограничиваете вставку для вставленных элементов.
Это более гибкий подход, и он даст вам легкость сохранить любую ту же или другую информацию от объекта к другой, поскольку вы должны реализовать интерфейс самостоятельно в своем классе.