Перегрузка метода Add LINQ для проверки
-
22-07-2019 - |
Вопрос
У меня есть объект Email
, и я пытаюсь проверить количество вложений в его свойстве List<Attachment>
.
Хитрость в том, что мы используем метод Send()
через службу WCF. Это легко проверить на стороне сервера, но сначала я хочу проверить это на стороне клиента.
Я создал библиотеку, которую другие должны использовать для использования службы, которая, в свою очередь, имеет прокси-сервер, содержащий все объекты и доступные методы. Я думаю, что я должен быть в состоянии перегрузить метод Add()
в GenericList с помощью некоторого пользовательского кода, чтобы коллекция проверялась при добавлении чего-либо, и, если она превышает указанный максимум, генерируется исключение.
public partial class List<Attachment>
{
public void Add(Attachment item)
{
base.Add(item);
if (this.Count() > maxAttachments)
{
throw new Exception("fail")
}
}
}
Это не работает - я не могу классифицировать base.Add () и не могу определить частичный класс с указанным типом.
Как создать перегрузку для метода Add, чтобы я мог включить некоторый пользовательский код?
Решение
Если у вас есть класс Email
, лучшим вариантом будет изменить базовый тип члена List на специализированную реализацию списка.
public class Email
{
const int MaxAttachments = /* ... */;
public Email(/* ... */)
{
this.Attachments = new FixedSizeList<Attachment>(MaxAttachments);
}
// ...
public IList<Attachment> Attachments
{
get;
private set;
}
}
class FixedSizeList<T> : IList<T>
{
List<T> innerList;
int maxCount;
public FixedSizeList(int maxCount)
{
this.innerList = new List<T>(maxCount);
this.maxCount = maxCount;
}
// override all the IList<T> members here by delegating
// to your innerList ...
// ...
public void Add(T item)
{
if (this.Count == this.maxSize)
{
throw new InvalidOperationException("No more items can be added.");
}
this.innerList.Add(item);
}
// ...
// ...
}
Это довольно много шаблонного кода, но это действительно единственный способ полностью изменить поведение.
Однако, если вы не владеете классом <=>, вы не сможете сделать это традиционными способами; вам понадобится рефлексия, чтобы заменить базовый элемент или что-то вроде Framework Managed Extensibility Framework . р>
Другие советы
List<T>
не является частичным классом, поэтому вы не можете расширить его, используя свои собственные частичные классы. Р>
Кроме того, LINQ to Objects не предоставляет Add()
для IList<T>
, это часть интерфейса System.Collections.ObjectModel.Collection<T>
, реализованного InsertItem()
, и RemoveItem()
не является виртуальным или абстрактным методом в <=>, поэтому Вы не можете переопределить это.
Обратите внимание на то, что <=> - этот компонент предоставляет реализацию списка, аналогичную <=>, с дополнительной возможностью переопределять защищенные методы, которые дают вам возможность выполнять задачи проверки.
Вам не нужно реализовывать список с нуля, вы просто наследуете его и переопределяете методы, такие как <=> и <=>, для реализации пользовательских правил:
using System.Collections.ObjectModel;
public class EmailCollection : Collection<Email>
{
public int MaximumAttachments { get; set; }
protected override void InsertItem(int index, Email item)
{
if (Count == MaximumAttachments)
{
... throw error
}
// do actual insert
base.InsertItem(index, item)
}
}
<=> звонит <=> под капот.