マネージ同期プロバイダーを作成する方法

このトピックでは、カスタム データ ストアからのデータを同期する Sync Framework 同期プロバイダーを、マネージ言語を使用して作成する方法について説明します。

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

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

同期プロバイダーについて

同期プロバイダーは、同期時のレプリカを表すソフトウェア コンポーネントです。レプリカは、同期プロバイダーを使用することで、そのデータを他のレプリカとの間で同期できるようになります。同期を実行するには、まず、アプリケーションで SyncOrchestrator オブジェクトを作成し、それを 2 つの SyncProvider オブジェクトに接続して同期を開始します。そのうちの 1 つは同期元のレプリカを表すプロバイダーです。変更された項目のメタデータは、同期元のレプリカから、その GetChangeBatch メソッドを介して提供されます。また、項目データは、IChangeDataRetriever オブジェクトを介して提供されます。もう 1 つは、同期先レプリカを表すプロバイダーです。同期先のレプリカは、変更された項目のメタデータを ProcessChangeBatch メソッドを介して受け取り、Sync Framework が備えている NotifyingChangeApplier オブジェクトと、それ独自の INotifyingChangeApplierTarget オブジェクトを使用することによって、項目ストアに変更を適用します。

同期プロバイダーのロールの詳細については、「標準のカスタム プロバイダーの実装」を参照してください。

ビルド要件

このトピックのコード例では、Sync Framework の同期コミュニティに対し、レプリカを同期元や同期先として参加させるために必要な、基本的なクラスとインターフェイスのメソッドの実装方法を紹介しています。この例のレプリカは、連絡先情報がコンマ区切りの値の一覧として保存されているテキスト ファイルです。同期する項目は、このファイルに含まれる連絡先です。この例では、Metadata Storage Service API を使って実装されたカスタム メタデータ ストアも使用されています。Metadata Storage Service の詳細については、「Sync Framework Metadata Storage Service」を参照してください。

この例の場合、_itemStore は、項目ストアとメタデータ ストアの両方を格納するオブジェクトを表します。

SyncProvider および KnowledgeSyncProvider の実装

プロバイダーへのエントリ ポイントは、SyncProvider クラスです。このクラスは、より強力な他のプロバイダー クラスの基本クラスとして使用されます。この例では、KnowledgeSyncProvider クラスを使用します。

KnowledgeSyncProvider の宣言

クラスの継承一覧に KnowledgeSyncProvider を追加します。

class ContactsProviderXmlMetadataNoChangeUnits : KnowledgeSyncProvider

クラスに SyncProvider メソッドと KnowledgeSyncProvider メソッドを追加します。

IdFormats プロパティ

Sync Framework は、SynchronizeSyncOrchestrator オブジェクトで呼び出されたときに、同期元と同期先の両方のプロバイダーの IdFormats を呼び出します。IdFormats プロパティは、そのプロバイダーが使用する ID 形式スキーマを返します。このスキーマは、両方のプロバイダーで一致している必要があります。この例では、SyncGlobalId を含む項目 ID、レプリカの絶対パスを含むレプリカ ID、および列挙のメンバーである変更単位 ID のサイズを定義します。

public override SyncIdFormatGroup IdFormats
{
    get 
    {
        SyncIdFormatGroup FormatGroup = new SyncIdFormatGroup();

        // Item IDs are of SyncGlobalId type, so they are fixed length and contain a ulong prefix plus a Guid.
        FormatGroup.ItemIdFormat.IsVariableLength = false;
        FormatGroup.ItemIdFormat.Length = (ushort)(sizeof(ulong) + Marshal.SizeOf(typeof(Guid)));

        // Replica IDs are the absolute path to the item store, so they are variable length with maximum
        // length equal to the maximum length of a path.
        FormatGroup.ReplicaIdFormat.IsVariableLength = true;
        FormatGroup.ReplicaIdFormat.Length = 260 * sizeof(char);

        return FormatGroup;
    }
}

BeginSession メソッド

Sync Framework は、どのメソッドを呼び出すよりも早く、同期元と同期先の両方のプロバイダーの BeginSession を呼び出します。このメソッドは、同期セッションに参加しようとしていることをプロバイダーに伝え、そのプロバイダーにセッション状態情報を含んだオブジェクトを渡します。この実装では、セッション状態オブジェクトが保存されます。プロバイダーが既に同期セッションに参加している場合は、SyncInvalidOperationException がスローされます。

public override void BeginSession(SyncProviderPosition position, SyncSessionContext syncSessionContext)
{
    // If this object is already in a session, throw an exception.
    if (null != _sessionContext)
    {
        throw new SyncInvalidOperationException();
    }
    
    _sessionContext = syncSessionContext;
}

GetSyncBatchParameters メソッド

Sync Framework は、同期先プロバイダーの GetSyncBatchParameters を呼び出します。これは、同期元プロバイダー側で変更バッチに含める必要のある変更の数を取得し、同期先プロバイダーの現在のナレッジを取得するメソッドです。この実装では、メタデータ ストアからナレッジを抽出し、バッチ サイズを 10 に設定しています。

public override void GetSyncBatchParameters(out uint batchSize, out SyncKnowledge knowledge)
{
    // Set a batch size of 10.
    batchSize = 10;

    // Return the current knowledge of the replica.
    knowledge = _itemStore.ContactReplicaMetadata.GetKnowledge();
}

このメタデータ ストア オブジェクトは、GetKnowledge を使用して、レプリカの現在のナレッジを返します。この実装では、レプリカにナレッジが含まれていない場合は新しい SyncKnowledge オブジェクトを作成し、そのナレッジのティック数をレプリカの現在のティック数に設定します。

public override SyncKnowledge GetKnowledge()
{
    // If the replica does not yet contain any knowledge, create a new knowledge object.
    if (null == _knowledge)
    {
        _knowledge = new SyncKnowledge(IdFormats, ReplicaId, _tickCount);            
    }

    // Ensure the tick count of the knowledge is set to the current tick count of the replica.
    _knowledge.SetLocalTickCount(_tickCount);

    return _knowledge;
}

GetChangeBatch メソッド

同期セッションが本格的に開始されるのは、Sync Framework によって同期元プロバイダーの GetChangeBatch が呼び出されたときです。このメソッドは、同期先プロバイダーに送信する変更のバッチを取得するほか、データ取得元インターフェイスを返します。Sync Framework は、同期先レプリカに適用された変更の項目データを取得するために同期先プロバイダーが使用する object を、データ取得元インターフェイスを使用して取得します。Sync Framework は、最後のバッチが送信されるまで、GetChangeBatch を繰り返し呼び出します。同期元プロバイダーは、変更バッチ オブジェクトで SetLastBatch メソッドを呼び出すことにより、バッチが最後のバッチであることを示します。この実装では、変更の列挙タスクはメタデータ ストア オブジェクトに委任されます。プロバイダー オブジェクトは IChangeDataRetriever を実装します。したがって、これは changeDataRetriever パラメーターに返されます。

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;

    // Call the metadata store to get a batch of changes.
    return _itemStore.ContactReplicaMetadata.GetChangeBatch(batchSize, destinationKnowledge);
}

このメタデータ ストア オブジェクトは、GetChangeBatch を使用して変更バッチを返します。この実装では、項目 ID で順序付けされた ItemMetadata オブジェクトの一覧として、項目がメタデータ ストアに保存されます。項目が列挙され、同期先ナレッジに変更が含まれていない場合は、変更バッチ オブジェクト内の順序付けられているグループに変更が追加されます。メタデータ ストア内のすべての項目が列挙されると、変更バッチで SetLastBatch が呼び出されます。

public override ChangeBatch GetChangeBatch(uint batchSize, SyncKnowledge destinationKnowledge)
{
    // The destination knowledge must be converted to be compatible with the source replica
    // before it can be used.
    SyncKnowledge mappedDestKnowledge = _knowledge.MapRemoteKnowledgeToLocal(destinationKnowledge);

    // Create a new change batch, initialized by using the current knowledge of the source replica
    // and a new ForgottenKnowledge object.
    ChangeBatch changeBatch = new ChangeBatch(IdFormats, GetKnowledge(), new ForgottenKnowledge());

    // Start a group of changes in the change batch. The group is ordered by item ID.
    // _getChangeBatchCurrent is 0 the first time GetChangeBatch is called, and is used to track the
    // position in the metadata store for subsequent calls to GetChangeBatch.
    changeBatch.BeginOrderedGroup(_items.Values[_getChangeBatchCurrent].GlobalId);
    
    // itemsAdded is incremented each time a change is added to the change batch. When itemsAdded
    // is greater than the requested batch size, enumeration stops and the change batch is returned.
    int itemsAdded = 0;
    
    ItemMetadata itemMeta;

    // Enumerate items and add a change to the change batch if it is not contained in the 
    // destination knowledge.
    // _items is a SortedList that contains ItemMetadata objects that are ordered by item ID.
    for (; itemsAdded <= batchSize && _getChangeBatchCurrent < _items.Count; _getChangeBatchCurrent++)
    {
        itemMeta = _items.Values[_getChangeBatchCurrent];
        ChangeKind kind = (itemMeta.IsDeleted) ? ChangeKind.Deleted : ChangeKind.Update;
        ItemChange change = new ItemChange(IdFormats, ReplicaId, itemMeta.GlobalId, kind, itemMeta.CreationVersion, 
            itemMeta.ChangeVersion);

        // If the change is not contained in the destination knowledge, add it to the change batch.
        if (!mappedDestKnowledge.Contains(change))
        {
            changeBatch.AddChange(change);
            itemsAdded++;
        }
    }

    // End the group of changes in the change batch. Pass the current source knowledge.
    changeBatch.EndOrderedGroup(_items.Values[_getChangeBatchCurrent - 1].GlobalId, _knowledge);

    // When all items in the metadata store have been enumerated, set this batch as the
    // last batch.
    if (_getChangeBatchCurrent == _items.Count)
    {
        changeBatch.SetLastBatch();
    }

    return changeBatch;
}

ProcessChangeBatch メソッド

Sync Framework が、同期元プロバイダーの GetChangeBatch メソッドを呼び出して、変更バッチを取得した後、Sync Framework は、同期先プロバイダーの ProcessChangeBatch を呼び出します。このメソッドによって、変更が同期先のレプリカへと適用されます。このメソッドは、同期元プロバイダーでの GetChangeBatch によって取得された各変更バッチにつき 1 回呼び出されます。この実装では、メタデータ ストア オブジェクトを使用して、同期元プロバイダーから項目のローカル バージョン情報を取得します。さらに、Sync Framework によって実装された NotifyingChangeApplier オブジェクトを作成して、その ApplyChanges メソッドを呼び出します。

public override void ProcessChangeBatch(ConflictResolutionPolicy resolutionPolicy, ChangeBatch sourceChanges, object changeDataRetriever, SyncCallbacks syncCallbacks, SyncSessionStatistics sessionStatistics)
{
    // Use the metadata store to get the local versions of changes received from the source provider.
    IEnumerable<ItemChange> destVersions = _itemStore.ContactReplicaMetadata.GetLocalVersions(sourceChanges);

    // Use a NotifyingChangeApplier object to process the changes. Note that this object is passed as the INotifyingChangeApplierTarget
    // object that will be called to apply changes to the item store.
    NotifyingChangeApplier changeApplier = new NotifyingChangeApplier(IdFormats);
    changeApplier.ApplyChanges(resolutionPolicy, sourceChanges, (IChangeDataRetriever)changeDataRetriever, destVersions,
        _itemStore.ContactReplicaMetadata.GetKnowledge(), _itemStore.ContactReplicaMetadata.GetForgottenKnowledge(), 
        this, _sessionContext, syncCallbacks);
}

メタデータ ストア オブジェクトは、GetLocalVersions を使用して、同期元プロバイダーから項目のローカル バージョン情報を返します。この実装によって、同期元プロバイダーから変更バッチとして送信された変更が列挙されます。項目が同期先メタデータに存在する場合は、そのバージョン情報がバージョン情報を含む変更の一覧に追加されます。項目が同期先メタデータに存在しない場合は、ローカル バージョンの一覧で不明な項目としてフラグが設定されます。

public override IEnumerable<ItemChange> GetLocalVersions(ChangeBatch sourceChanges)
{
    List<ItemChange> localVersions = new List<ItemChange>();

    // Enumerate the source changes and retrieve the destination version for each source change. 
    foreach (ItemChange srcItem in sourceChanges)
    {
        ItemChange localVer;

        // When the source item exists in the destination metadata store, retrieve the destination version of the item.
        if (_items.ContainsKey(srcItem.ItemId))
        {
            XmlItemMetadata localMeta = _items[srcItem.ItemId];
            ChangeKind kind = (localMeta.IsDeleted) ? ChangeKind.Deleted : ChangeKind.Update;
            localVer = new ItemChange(IdFormats, ReplicaId, srcItem.ItemId, kind, localMeta.CreationVersion, localMeta.ChangeVersion);
        }
        // When the source item does not exist in the destination metadata store, create a new change with unknown
        // version information.
        else
        {
            localVer = new ItemChange(IdFormats, ReplicaId, srcItem.ItemId, ChangeKind.UnknownItem, SyncVersion.UnknownVersion, SyncVersion.UnknownVersion);
        }

        localVersions.Add(localVer);
    }

    return localVersions;
}

EndSession メソッド

同期元プロバイダーから最新のバッチが送信され、変更が同期先プロバイダーのデータ ストアに適用されると、Sync Framework が、同期元と同期先の両方のプロバイダーの EndSession を呼び出します。このメソッドにより、同期セッションが終了し、セッションに関連付けられたリソースをすべて解放する必要があるという情報が、プロバイダーに伝えられます。この実装により、BeginSession の呼び出しで保存されたセッション状態オブジェクトが解放されます。プロバイダーが同期セッションに参加していなかった場合は、SyncInvalidOperationException がスローされます。

public override void EndSession(SyncSessionContext syncSessionContext)
{
    // If this object is not in a session, throw an exception.
    if (null == _sessionContext)
    {
        throw new SyncInvalidOperationException();            
    }

    _sessionContext = null;
}

実装されないメソッド

このサンプルでは、削除マークの付いた項目をメタデータ ストアから削除することはしません。したがって、次に示したメソッドは不要です。これらのメソッドは、NotImplementedException をスローすることがあります。

INotifyingChangeApplierTarget の実装

このインターフェイスは、同期先プロバイダーが ApplyChanges メソッドを (通常は ProcessChangeBatch メソッドで) 呼び出すときに、Sync Framework に提供されます。INotifyingChangeApplierTarget には、変更の適用時に呼び出されるメソッドが存在します。これらのメソッドは、同期先プロバイダーでのみ呼び出されます。

INotifyingChangeApplierTarget の宣言

クラスの継承一覧に INotifyingChangeApplierTarget を追加します。

class ContactsProviderXmlMetadataNoChangeUnits : KnowledgeSyncProvider
    , INotifyingChangeApplierTarget

クラスに INotifyingChangeApplierTarget メソッドを追加します。

IdFormats プロパティ

Sync Framework は、IdFormats を呼び出して、プロバイダーの ID 形式スキーマを取得します。この例では、同じクラスを使用して、KnowledgeSyncProviderINotifyingChangeApplierTarget の両方を実装します。したがって、この実装は、前の KnowledgeSyncProviderIdFormats プロパティの実装と同じです。

GetNextTickCount

Sync Framework は、GetNextTickCount を呼び出すことによって、レプリカのティック数をインクリメントしたり取得したりします。この実装では、メタデータ ストア オブジェクトの GetNextTickCount メソッドを呼び出します。

public ulong GetNextTickCount()
{
    return _itemStore.ContactReplicaMetadata.GetNextTickCount();
}

GetNextTickCount のメタデータ ストアの実装では、レプリカのティック数をインクリメントして返します。

public override ulong GetNextTickCount()
{
    return ++_tickCount;
}

SaveItemChange

変更の適用時には、Sync Framework が、同期先レプリカに適用される各変更について、SaveItemChange を呼び出します。この実装では、受信した変更の種類ごとに項目ストアとメタデータ ストアを更新します。項目が作成または更新されると、context パラメーターの ChangeData プロパティにその項目のデータが入力されます。ChangeData プロパティには、同期元プロバイダーの LoadChangeData メソッドから返された object が含まれます。変更が適用された後、更新された同期先ナレッジが保存されます。

public void SaveItemChange(SaveChangeAction saveChangeAction, ItemChange change, SaveChangeContext context)
{
    switch (saveChangeAction)
    {
        // Update the item store and metadata store when an item is created or updated.
        case SaveChangeAction.Create:
        case SaveChangeAction.UpdateVersionAndData:
        {
            try
            {
                _itemStore.UpdateContactFromSync(change, (string)context.ChangeData);
            }
            catch (Exception ex)
            {
                RecoverableErrorData errData = new RecoverableErrorData(ex);
                context.RecordRecoverableErrorForItem(errData);
            }
            break;
        }

        // Update only the version of this item in the metadata store.
        case SaveChangeAction.UpdateVersionOnly:
        {
            try
            {
                _itemStore.UpdateContactVersion(change.ItemId, change.ChangeVersion);
            }
            catch (Exception ex)
            {
                RecoverableErrorData errData = new RecoverableErrorData(ex);
                context.RecordRecoverableErrorForItem(errData);
            }
            break;
        }

        // Delete the item from the item store and store a tombstone for it in the metadata store.
        case SaveChangeAction.DeleteAndStoreTombstone:
        {
            try
            {
                _itemStore.DeleteContactFromSync(change.ItemId, change.ChangeVersion);
            }
            catch (Exception ex)
            {
                RecoverableErrorData errData = new RecoverableErrorData(ex);
                context.RecordRecoverableErrorForItem(errData);
            }

            break;
        }

        // Neither merging of data nor removing tombstones is supported.
        case SaveChangeAction.UpdateVersionAndMergeData:
        case SaveChangeAction.DeleteAndRemoveTombstone:
        {
            throw new NotImplementedException();
        }

        default:
        {
            throw new ArgumentOutOfRangeException();
        }
    }

    // Save the knowledge in the metadata store as each change is applied. Saving knowledge as each change is applied is 
    // not required. It is more robust than saving the knowledge only after each change batch, because if synchronization is interrupted 
    // before the end of a change batch, the knowledge will still reflect all of the changes applied. However, it is less efficient because 
    // knowledge must be stored more frequently.
    SyncKnowledge knowledge;
    ForgottenKnowledge forgottenKnowledge;
    context.GetUpdatedDestinationKnowledge(out knowledge, out forgottenKnowledge);
    _itemStore.ContactReplicaMetadata.SetKnowledge(knowledge);
}

次の例では、_ContactItemMetaListItemMetadata オブジェクトが含まれています。

連絡先ストアの UpdateContactFromSync メソッドは、指定された連絡先を更新します。連絡先が存在しない場合は、新しい連絡先が作成され、連絡先ストアに追加されます。メタデータ ストアも更新され、連絡先ストアに対する変更が反映されます。

public void UpdateContactFromSync(ItemChange itemChange, string changeData)
{
    // If the item does not exist, create a new contact and add it to the contact and metadata store.
    if (!_ContactList.ContainsKey(itemChange.ItemId))
    {
        Contact contact = new Contact();
        ItemMetadata newItemMeta = _ContactReplicaMetadata.CreateItemMetadata(itemChange.ItemId,
            itemChange.CreationVersion);

        _ContactList.Add(newItemMeta.GlobalId, contact);
        _ContactItemMetaList.Add(newItemMeta.GlobalId, newItemMeta);
    }

    // Update the specified contact in the contact store. changeData is the contact data returned by the
    // IChangeDataRetriever.LoadChangeData method of the source provider.
    _ContactList[itemChange.ItemId].FromString(changeData);

    // Get the metadata for the specified item.
    ItemMetadata itemMeta = _ContactItemMetaList[itemChange.ItemId];

    // Update the index fields for the item. This implementation defines an index that uniquely identifies each contact.
    // The index consists of the first name, last name, and phone number of the contact.
    itemMeta.SetCustomField(FirstNameField, _ContactList[itemChange.ItemId].FirstName);
    itemMeta.SetCustomField(LastNameField, _ContactList[itemChange.ItemId].LastName);
    itemMeta.SetCustomField(PhoneNumberField, _ContactList[itemChange.ItemId].PhoneNumber);

    // Update the version for the change.
    itemMeta.ChangeVersion = itemChange.ChangeVersion;
}

連絡先ストアの UpdateContactVersion メソッドは、指定された項目のバージョン メタデータを更新します。

public void UpdateContactVersion(SyncId itemId, SyncVersion itemVersion)
{
    // Update the version metadata for the specified item.
    _ContactItemMetaList[itemId].ChangeVersion = itemVersion;
}

連絡先ストアの DeleteContactFromSync メソッドは、連絡先ストアから項目を削除し、メタデータ ストアに項目が削除されたという記録を付けます。

public void DeleteContactFromSync(SyncId itemId, SyncVersion version)
{
    if (_ContactList.ContainsKey(itemId))
    {
        // Remove the item from the contact store.
        _ContactList.Remove(itemId);

        // Mark the item as deleted in the metadata store.
        ItemMetadata itemMeta = _ContactItemMetaList[itemId];
        itemMeta.MarkAsDeleted(version);

        // Change the first index field so the index fields don't collide with future items.
        itemMeta.SetCustomField(FirstNameField, itemId.ToString());

        // Move the metadata for the deleted item to a separate list. 
        // The deleted item metadata must be kept so that it can be committed when
        // SaveChanges is called.
        _ContactDeletedItemMetaList.Add(itemMeta);
        _ContactItemMetaList.Remove(itemId);
    }
    else 
    {
        // An item marked as deleted has been received as part of synchronization, but it does not exist in
        // the item store. Create a tombstone for it in the metadata store.
        ItemMetadata itemMeta = _ContactReplicaMetadata.CreateItemMetadata(itemId, version);
        itemMeta.MarkAsDeleted(version);

        // Clear the index fields so they don't collide with future items.
        itemMeta.SetCustomField(FirstNameField, itemId.ToString());

        _ContactDeletedItemMetaList.Add(itemMeta);
    }
}

StoreKnowledgeForScope

各変更バッチを処理した後、Sync Framework は、同期先プロバイダーが、新しい変更を含んだナレッジを保存できるよう、StoreKnowledgeForScope を呼び出します。この実装では、ナレッジ オブジェクトがメタデータ ストアに保存され、また、既存のナレッジは上書きされます。変更バッチの処理中に連絡先ストアとメタデータ ストアに加えられた変更は、ディスク上のファイルにコミットされます。

public void StoreKnowledgeForScope(SyncKnowledge knowledge, ForgottenKnowledge forgottenKnowledge)
{
    _itemStore.ContactReplicaMetadata.SetKnowledge(knowledge);

    // Commit changes made to the in-memory item store to the file on disk.
    _itemStore.SaveContactChanges();

    // Commit changes made to the in-memory metadata store to the file on disk.
    _itemStore.SaveMetadataChanges();
}

連絡先ストアの SaveMetadataChanges メソッドは、メタデータ ストアに加えられた変更をディスク上のファイルにコミットします。

public void SaveMetadataChanges()
{
    // A transaction is required for saving changes to the metadata store.
    _ContactMetadataStore.BeginTransaction(IsolationLevel.ReadCommitted);

    // Enumerate the deleted items list.
    if (null != _ContactDeletedItemMetaList)
    {
        foreach (ItemMetadata contactMeta in _ContactDeletedItemMetaList)
        {
            // Save the deleted item metadata to the metadata store.
            _ContactReplicaMetadata.SaveItemMetadata(contactMeta);
        }
    }

    // Save renamed items first to avoid collisions in the metadata store.
    foreach (SyncId itemId in _ContactRenameList)
    {
        _ContactReplicaMetadata.SaveItemMetadata(_ContactItemMetaList[itemId]);            
    }

    // Enumerate the active contacts.
    for (int iCon = 0; iCon < _ContactItemMetaList.Count; iCon++)
    { 
        // Save the item metadata to the metadata store.
        _ContactReplicaMetadata.SaveItemMetadata(_ContactItemMetaList.Values[iCon]);
    }

    // Save the replica metadata to the metadata store.
    _ContactReplicaMetadata.SaveReplicaMetadata();

    // Commit the metadata store transaction.
    _ContactMetadataStore.CommitTransaction();
}

実装されないメソッド

基本的な同期シナリオでは次のメソッドは不要であり、NotImplementedException がスローされる場合があります。

IChangeDataRetriever の実装

Sync Framework には、GetChangeBatch の呼び出しの応答として、同期元プロバイダーから IChangeDataRetriever が返されます。IChangeDataRetriever は、ProcessChangeBatch の呼び出しで、同期先プロバイダーに送信されます (通常は、変更適用元の ApplyChanges メソッドに渡されます)。さらに、変更適用元は、LoadChangeData を呼び出して、項目データを表す object を取得します。変更適用元は、このインターフェイスを同期先プロバイダーの SaveItemChange メソッドまたは SaveChangeWithChangeUnits メソッドに渡します。同期先プロバイダーは、この object を使用して、新しい項目や変更された項目の項目データを取得し、それを同期先レプリカに適用します。

IChangeDataRetriever の宣言

クラスの継承一覧に IChangeDataRetriever を追加します。

class ContactsProviderXmlMetadataNoChangeUnits : KnowledgeSyncProvider
    , INotifyingChangeApplierTarget
    , IChangeDataRetriever

クラスに IChangeDataRetriever メソッドを追加します。

IdFormats プロパティ

Sync Framework は、IdFormats を呼び出して、プロバイダーの ID 形式スキーマを取得します。この例では、同じクラスを使用して、KnowledgeSyncProviderIChangeDataRetriever の両方を実装します。したがって、この実装は、前の KnowledgeSyncProviderIdFormats プロパティの実装と同じです。

LoadChangeData メソッド

変更の適用時、Sync Framework は、LoadChangeData を呼び出して object を取得します。同期先プロバイダーは、このオブジェクトを使用して項目データを取得できます。この実装では、文字列としてシリアル化された連絡先データが返されます。

public object LoadChangeData(LoadChangeContext loadChangeContext)
{
    // Return the specified contact serialized as a string.
    return _itemStore.ContactList[loadChangeContext.ItemChange.ItemId].ToString();
}

次の手順

同期セッションをホストするアプリケーションを作成して、それをプロバイダーに接続することもできます。具体的な方法については、「アンマネージ同期アプリケーションを作成する方法」を参照してください。

プロバイダーの機能を強化して、同期する項目や変更単位をフィルター処理することもできます。フィルター選択の詳細については、「同期データのフィルター設定」を参照してください。

プロバイダーの機能を強化して、変更単位を処理することもできます。変更単位の詳細については、「変更単位の同期」を参照してください。

さらに、カスタム メタデータ ストアを作成することもできます。同期メタデータを処理する方法の詳細については、「標準プロバイダーのメタデータの管理」を参照してください。

参照

リファレンス

SyncProvider
KnowledgeSyncProvider
INotifyingChangeApplierTarget
IChangeDataRetriever
NotifyingChangeApplier

概念

標準のカスタム プロバイダーの実装
Sync Framework のコア コンポーネント