Вопрос

У меня есть объект 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)
    }
}

<=> звонит <=> под капот.

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top