Question

I have an Email object and am attempting to validate the number of attachments that are in its List<Attachment> property.

The trick is that we consume the Send() method across a WCF service. It's easy to validate it server side, but I want to validate it client side first.

I have generated a library that others are supposed to use in order to consume the service, which in turn has a proxy containing all the objects and available methods. I think I should be able to overload the Add() method on the GenericList with some custom code so the collection is checked when anything is added, and if it exceeds the specified maximum then an exception is thrown.

public partial class List<Attachment>
{
    public void Add(Attachment item)
    {
        base.Add(item);
        if (this.Count() > maxAttachments)
        {
            throw new Exception("fail")
        }
    }
}

This doesn't work - I can't class base.Add() and I can't define partial class with a specified type.

How do I create an overload for the Add method so that I can include some custom code?

Was it helpful?

Solution

If you own the Email class, your best option would be to change the underlying type of the List member to a specialized implementation of a 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);
    }

    // ...
    // ...
}

It's kind of a lot of boilerplate code, but that's really the only way to cleanly override the behavior.

However, if you don't own the Email class, you can't really do this through traditional means; you'd need a reflection hack to replace the underlying member or something like the Managed Extensibility Framework.

OTHER TIPS

List<T> is not a partial class, so you can't extend it using your own partial classes.

Also, LINQ to Objects does not provide Add() on List<T>, that's part of the IList<T> interface implemented by List<T>, and Add() is not a virtual or abstract method in List<T>, so you can't override it.

What you should look at is System.Collections.ObjectModel.Collection<T> - this component provides a list implementation similar to List<T> with the added capacity to override protected methods that give you a place to do validation tasks.

You don't have to implement the list from scratch, you just inherit from it, and override methods such as InsertItem() and RemoveItem() to implement custom rules:


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

Add() calls InsertItem() under the hood.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top