如何筛选枚举项

本主题说明如何使用托管语言筛选 Sync Framework 同步提供程序(它同步自定义数据存储区的数据)枚举的项。

本主题假定您基本熟悉 C# 和 Microsoft .NET Framework 概念。

本主题中的示例着重介绍以下 Sync Framework 类和成员:

了解项筛选

项筛选器可以限制源提供程序在变更枚举期间发送哪些项变更,例如只发送文件夹中的 .txt 文件,而忽略其他类型的文件。如果变更会导致现有项移入或移出筛选器,则项不得采用此方式变更。项筛选器简单易用,但用于同步的元数据随着同步作用域中项数的增长而成比例增长。如果涉及存储,则适合采用自定义筛选器。有关自定义筛选的更多信息,请参见筛选同步数据

定义项的筛选方式不由 Sync Framework 进行,通常由提供程序开发人员或者第三方进行。筛选器可由同步应用程序通过使用在应用程序和提供程序之间适合的任何机制设置,或者可在两个提供程序之间进行协商。有关协商筛选器的更多信息,请参见筛选同步数据

目标提供程序像对待标准变更批一样接收和应用变更。无需为进行筛选而采取特殊操作。

生成要求

示例

本主题中的示例代码演示如何实现一个简单的项筛选器以及如何使用元数据存储服务生成筛选的变更批。本示例中的副本是一个文本文件,它将联系信息以逗号分隔的值列表形式存储。要同步的项是此文件中包含的联系人。筛选器定义为只包括其出生日期字段小于应用程序指定的值的联系人。

设置筛选器

源提供程序实现一个公共方法,该方法允许应用程序设置一个筛选器,该筛选器定义出生日期字段的最大值。只要联系人的出生日期字段中的值超过该最大值,该联系人就不会包括在变更批中。

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,这样在指定了某一筛选器时,它使用元数据存储服务来生成筛选的变更批。这是通过创建 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 委托。元数据存储服务调用此委托,并且使用返回值以便从变更批中包括或排除项。在这个示例中,当出生日期字段的值小于指定的最大出生日期时,项将包括在变更批中。

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

后续步骤

接下来,您可能要向您的提供程序添加筛选器协商功能,以便它可与目标提供程序通信以便确定哪一筛选器要用于变更枚举。有关如何协商筛选器的更多信息,请参见如何协商筛选器

您可能还要使用自定义筛选器,而非项筛选器。自定义筛选器需要涉及更多的工作,但跟踪和通信的效率会高得多,因此在使用自定义筛选器时可保持较少的同步元数据。有关自定义筛选器的更多信息,请参见筛选同步数据

请参阅

概念

对常见标准自定义提供程序任务进行编程
筛选同步数据