検証のためのLINQのAddメソッドのオーバーロード
-
22-07-2019 - |
質問
Email
オブジェクトがあり、そのList<Attachment>
プロパティにある添付ファイルの数を検証しようとしています。
コツは、WCFサービス全体でSend()
メソッドを使用することです。サーバー側で簡単に検証できますが、最初にクライアント側で検証したいです。
サービスを利用するために他の人が使用することになっているライブラリを生成しました。このライブラリには、すべてのオブジェクトと利用可能なメソッドを含むプロキシがあります。 GenericListのAdd()
メソッドをいくつかのカスタムコードでオーバーロードできるようにすると、何かが追加されたときにコレクションがチェックされ、指定された最大値を超えると例外がスローされます。
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);
}
// ...
// ...
}
これは多くの定型コードですが、実際に動作を完全にオーバーライドする唯一の方法です。
ただし、<=>クラスを所有していない場合、従来の方法ではこれを実行できません。基礎となるメンバーまたは 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)
}
}
<=>は内部で<=>を呼び出します。