列挙された項目をフィルターする方法

このトピックでは、カスタム データ ストアからのデータを同期する Sync Framework 同期プロバイダーによって列挙された項目を、マネージ言語を使用してフィルターで選択する方法について説明します。

このトピックは、C# および Microsoft .NET Framework の概念について基本的な知識がある方を対象としています。

このトピックの例では、次に示す Sync Framework のクラスとメンバーを中心に説明します。

項目のフィルター選択について

項目フィルターは変更の列挙時に同期元プロバイダーによって送信される項目変更を制限します。たとえば、ファイル フォルダー内の .txt ファイルのみを送信し、他の種類のファイルは無視するといったことができます。既存の項目の一致状態 (フィルター条件に一致するかどうか) が変化するような項目の変更が行われないようにする必要があります。項目フィルターの使用は容易ですが、同期に使用されるメタデータは、同期スコープ内の項目数に比例して増加します。ストレージを気にする必要がある場合は、カスタム フィルターが適しています。カスタム フィルターの詳細については、「同期データのフィルター設定」を参照してください。

項目のフィルター方法の定義は Sync Framework の外で、通常はプロバイダー開発者またはサードパーティによって行われます。同期アプリケーションは適切なメカニズムを自由に使ってプロバイダーと同期アプリケーション間にフィルターを設定できます。フィルターを 2 つのプロバイダー間でネゴシエートすることもできます。フィルターのネゴシエーションの詳細については、「同期データのフィルター設定」を参照してください。

同期先プロバイダーは、標準の変更バッチの場合と同様の方法で変更を受け取り適用します。フィルターに伴う特別の処理は要求されません。

ビルド要件

このトピックのコード例では、フィルターされた変更バッチを作成するための簡単な項目フィルターの実装方法と Metadata Storage Service の使用方法を示します。この例のレプリカは、連絡先情報がコンマ区切りの値の一覧として保存されているテキスト ファイルです。同期する項目は、このファイルに含まれる連絡先です。フィルターは生年月日フィールドの値がアプリケーションによって指定された値より小さい連絡先のみを含めるように定義されています。

フィルターの設定

同期元プロバイダーはパブリック メソッドを実装して、アプリケーションが生年月日フィールドの最大値を定義するフィルターを設定できるようにします。この値より大きな生年月日を持つ連絡先は変更バッチに含まれません。

public void SetMaximumBirthdateFilter(DateTime maxBirthdateFilter)
{
    // Store the fact that a filter is set, and the value of the filter.
    _isFiltered = true;
    _maxBirthdateFilter = maxBirthdateFilter;
}

同期アプリケーションは同期元プロバイダーをローカル プロバイダーとして作成し、SetMaximumBirthdateFilter メソッドを使って変更の列挙に含める生年月日の最大値を指定します。同期アプリケーションは同期先プロバイダーも作成して、同期を実行します。

private void SynchronizeWithItemFiltering(ContactStore localStore, ContactStore remoteStore, SyncDirectionOrder syncDir)
{
    // Create the local provider and set the item filter.
    // The filter is ignored when the provider is the destination provider.
    SyncProvider localProvider = new ContactsProviderItemFiltering(localStore);
    // Only include contacts with a birthdate before January 1, 2000.
    ((ContactsProviderItemFiltering)localProvider).SetMaximumBirthdateFilter(
        new DateTime(2000, 1, 1));

    // Create the remote provider and do not set a filter.
    SyncProvider remoteProvider = new ContactsProviderItemFiltering(remoteStore);

    // Create the synchronization orchestrator and set the providers and synchronization direction.
    SyncOrchestrator orchestrator = new SyncOrchestrator();
    orchestrator.LocalProvider = localProvider;
    orchestrator.RemoteProvider = remoteProvider;
    orchestrator.Direction = syncDir;

    string msg;
    try
    {
        // Synchronize data between the two providers.
        SyncOperationStatistics stats = orchestrator.Synchronize();

        // Display statistics for the synchronization operation.
        msg = "Synchronization succeeded!\n\n" +
            stats.DownloadChangesApplied + " download changes applied\n" +
            stats.DownloadChangesFailed + " download changes failed\n" +
            stats.UploadChangesApplied + " upload changes applied\n" +
            stats.UploadChangesFailed + " upload changes failed";
    }
    catch (Exception ex)
    {
        msg = "Synchronization failed! Here's why: \n\n" + ex.Message;
    }
    MessageBox.Show(msg, "Synchronization Results");
}

フィルターされた変更バッチの列挙

同期元プロバイダーは GetChangeBatch を実装して、フィルターが指定されたら、フィルターされた変更バッチを作成するときに Metadata Storage Service を使用できるようにします。これは ItemListFilterInfo オブジェクトを作成して、それを ReplicaMetadata オブジェクトの GetFilteredChangeBatch メソッドに渡すことによって行われます。

public override ChangeBatch GetChangeBatch(uint batchSize, SyncKnowledge destinationKnowledge, out object changeDataRetriever)
{
    // Return this object as the IChangeDataRetriever object that is called to retrieve item data.
    changeDataRetriever = this;

    // Use the metadata storage service to get a batch of changes.
    ChangeBatch retrievedBatch;
    if (_isFiltered)
    {
        // If a filter is set, get a filtered change batch from the metadata storage service.
        // The BirthdateFilterCallback method indicates whether an item passes the filter.
        ItemListFilterInfo filterInfo = new ItemListFilterInfo(IdFormats);
        retrievedBatch = _ContactStore.ContactReplicaMetadata.GetFilteredChangeBatch(batchSize, destinationKnowledge,
            filterInfo, BirthdateFilterCallback);
    }
    else
    {
        retrievedBatch = _ContactStore.ContactReplicaMetadata.GetChangeBatch(batchSize, destinationKnowledge);
    }

    return retrievedBatch;
}

項目がフィルターに含まれるかどうかを判定するために、GetFilteredChangeBatch メソッドは同期元プロバイダーによって実装された ItemFilterCallback デリゲートを使用します。Metadata Storage Service はこのデリゲートを呼び出し、その戻り値を使って項目を変更バッチに含めるか除外するかを決めます。この例では、生年月日フィールドの値が指定された最大生年月日より小さい項目が変更バッチに含められます。

public bool BirthdateFilterCallback(ItemMetadata itemMeta)
{
    // An item passes the filter only if its birthdate field is less than the maximum birthdate
    // specified by the filter.
    return (_ContactStore.ContactList[itemMeta.GlobalId].Birthdate < _maxBirthdateFilter);
}

次の手順

次は、フィルター ネゴシエーションをプロバイダーに追加して、変更列挙にどのフィルターを使用するかを同期先プロバイダーと通信して決定できるようにします。フィルターのネゴシエーションの詳細については、「フィルター ネゴシエーションの方法」を参照してください。

項目フィルターの代わりにカスタム フィルターを使用することもできます。カスタム フィルターの実装には手間がかかりますが、追跡や通信の効率がよくなり、その使用によって同期メタデータを小さくできます。カスタム フィルターの詳細については、「同期データのフィルター設定」を参照してください。

参照

概念

標準のカスタム プロバイダーをプログラミングするための一般的なタスク
同期データのフィルター設定