공급자 간의 데이터 변환
많은 응용 프로그램에서 모든 공급자는 정확하게 같은 종류의 데이터를 같은 형식으로 동기화합니다. 예를 들어 몇몇 데이터베이스 동기화 공급자는 ADO.NET 데이터 집합의 테이블 집합에 대해 데이터를 동기화하고 전송할 수 있습니다. 그러나 데이터 형식은 경우에 따라 달라질 수 있습니다. 연락처를 동기화하는 응용 프로그램을 생각해 보면 응용 프로그램에서 두 명의 다른 개발자가 작성한 사용자 지정 공급자를 사용할 경우 이러한 공급자에 필요한 데이터가 다음과 같은 두 가지 측면에서 차이가 날 수 있습니다.
공급자 A는 바이트 스트림으로 데이터를 전송하는 반면 공급자 B는 XML 스트림으로 데이터를 전송합니다.
공급자 A의 데이터는 FirstName, LastName 및 PhoneNumber라는 세 필드로 구성되고, 공급자 B의 데이터는 FirstName 및 LastName을 포함하지만 PhoneNumber가 PhoneNumber와 AreaCode로 나눠집니다.
이 시나리오를 처리하려면 Sync Framework에서 데이터를 각 공급자에 필요한 형식으로 변환하는 인터페이스를 구현해야 합니다. 이 경우 두 가지 변환을 수행하는 변환기를 작성할 수 있습니다. 첫 번째는 바이트 스트림 입력을 XML 출력으로 변환하는 것이고, 두 번째는 XML 입력을 바이트 스트림 출력으로 변환하는 것입니다. Sync Framework에서는 두 공급자 모두에게 변환기를 지정하지 않아도 됩니다. 구현하는 데이터 변환 코드는 동기화 세션에서 호출되어 변경 내용 적용 프로세스 동안 데이터 변환이 대상 공급자에 인식되지 않습니다.
또한 다양한 데이터 형식을 가진 많은 수의 공급자에 대해 서로 데이터를 동기화해야 하는 시나리오를 생각해 보면 가능한 방법 중 하나는 각 공급자 쌍에 대한 변환기를 작성하는 것이지만 관리하기 어려워질 수 있습니다. 더 좋은 방법은 각 공급자에 대해 데이터와 중간 형식 간에 변환하는 변환기를 작성하는 것입니다. 이 경우 두 가지 데이터 변환이 수행됩니다. 하나는 원본 공급자에서 중간 형식으로 변환하는 것이고, 다른 하나는 중간 형식에서 대상 공급자 형식으로 변환하는 것입니다.
다음 표에서는 데이터 변환에 대해 Sync Framework에서 제공되는 인터페이스 및 속성을 보여 줍니다.
관리 코드 | 비관리 코드 |
---|---|
|
다음 방법을 사용하여 각 공급자의 데이터를 변환합니다.
각 공급자의 변환기를 구현합니다.
관리 코드 두 필수 SyncDataConverter 메서드인 ConvertDataFromProviderFormat 및 ConvertDataToProviderFormat을 구현합니다.
비관리 코드 두 필수 ISyncDataConverter 메서드인 ConvertDataFromProviderFormat 및 ConvertDataToProviderFormat을 구현합니다.
동기화 세션 중에 사용할 변환기를 지정합니다.
관리 코드 구현한 변환기를 두 SyncOrchestrator 속성인 LocalDataConverter 및 RemoteDataConverter로 지정합니다.
비관리 코드 구현한 변환기를 두 ISyncDataConversionControl 메서드인 SetSourceDataConverter 및 SetDestinationDataConverter에 지정합니다.
대부분의 경우 사용할 수 있는 네 가지 변환 메서드 중 두 개만 구현하고 동기화 세션에 지정하게 됩니다. 데이터 검색자 변환과 관련된 두 메서드는 사용하는 데이터 검색자가 IChangeDataRetriever(관리 코드의 경우) 또는 IAsynchronousDataRetriever 또는 ISynchronousDataRetriever(비관리 코드의 경우)의 구현이 아닌 경우에만 필요합니다. 데이터를 중간 상태로 변환하는 상황에서 Sync Framework 데이터 검색자 인터페이스의 구현을 사용해야 합니다.
Sync Framework에서는 하나 또는 두 공급자가 관리되지 않는 경우 관리되는 응용 프로그램에서 데이터 변환을 지원합니다. 변환 프로세스는 항상 관리되는 개체에서 처리된다는 점에 유의하십시오. 이로 인해 응용 프로그램이 관리되지 않으면 동기화 시간이 오래 걸릴 수 있습니다.
코드 예
다음 코드 예제는 데이터 변환이 필요한 두 공급자를 동기화하는 방법을 보여줍니다. Execute
메서드에서 코드는 먼저 동기화될 공급자를 인스턴스화한 다음 입력 및 출력 형식을 허용하는 데이터 변환 클래스의 두 인스턴스를 인스턴스화합니다. 이 예제에서 ConvertDataFromProviderFormat
및 ConvertDataToProviderFormat
메서드는 데이터를 변경하지 않고 반환하지만 실제 응용 프로그램에서는 입력 형식을 적절한 출력 형식으로 변환해야 합니다.
public class SampleConversion
{
public void Execute()
{
SyncOrchestrator orchestrator = new SyncOrchestrator();
orchestrator.Direction = SyncDirectionOrder.Upload;
orchestrator.LocalProvider = new SampleSyncProvider(localStore);
orchestrator.RemoteProvider = new SampleSyncProvider(remoteStore);
DataConverter<DataObject1, DataObject2> localConverter = new DataConverter<DataObject1, DataObject2>();
DataConverter<DataObject2, DataObject3> remoteConverter = new DataConverter<DataObject2, DataObject3>();
orchestrator.LocalDataConverter = localConverter;
orchestrator.RemoteDataConverter = remoteConverter;
orchestrator.Synchronize();
}
string localStore;
string remoteStore;
}
public class DataConverter<SourceType, DestType> : SyncDataConverter
where SourceType : IDataObject, new()
where DestType : IDataObject, new()
{
public DataConverter()
{
}
public override object ConvertDataFromProviderFormat(LoadChangeContext loadChangeContext, object itemData)
{
SourceType dataObj = (SourceType)itemData;
DestType returnData = new DestType();
returnData.Data = dataObj.Data;
return returnData;
}
public override object ConvertDataToProviderFormat(LoadChangeContext loadChangeContext, object itemData)
{
DestType dataObj = (DestType)itemData;
SourceType returnData = new SourceType();
returnData.Data = dataObj.Data;
return returnData;
}
Type sourceType;
Type destType;
}
Public Class SampleConversion
Public Sub Execute()
Dim orchestrator As New SyncOrchestrator()
orchestrator.Direction = SyncDirectionOrder.Upload
orchestrator.LocalProvider = New SampleSyncProvider(localStore)
orchestrator.RemoteProvider = New SampleSyncProvider(remoteStore)
Dim localConverter As New DataConverter(Of DataObject1, DataObject2)()
Dim remoteConverter As New DataConverter(Of DataObject2, DataObject3)()
orchestrator.LocalDataConverter = localConverter
orchestrator.RemoteDataConverter = remoteConverter
orchestrator.Synchronize()
End Sub
Private localStore As String
Private remoteStore As String
End Class
Public Class DataConverter(Of SourceType As {IDataObject, New}, DestType As {IDataObject, New})
Inherits SyncDataConverter
Public Sub New()
End Sub
Public Overloads Overrides Function ConvertDataFromProviderFormat(ByVal loadChangeContext As LoadChangeContext, ByVal itemData As Object) As Object
Dim dataObj As SourceType = DirectCast(itemData, SourceType)
Dim returnData As New DestType()
returnData.Data = dataObj.Data
Return returnData
End Function
Public Overloads Overrides Function ConvertDataToProviderFormat(ByVal loadChangeContext As LoadChangeContext, ByVal itemData As Object) As Object
Dim dataObj As DestType = DirectCast(itemData, DestType)
Dim returnData As New SourceType()
returnData.Data = dataObj.Data
Return returnData
End Function
Private sourceType As Type
Private destType As Type
End Class
다음 코드 예제에서는 데이터 검색 변환 메서드인 TryConvertDataRetrieverFromProviderFormat
및 TryConvertDataRetrieverToProviderFormat
을 정의합니다. 두 메서드 모두 데이터 검색자와 변경 내용의 목록을 허용합니다. 데이터 검색자 변환을 수행하기 위해 IChangeDataRetriever
를 상속하는 ConvertedDataRetriever
샘플 클래스를 인스턴스화합니다.
public override bool TryConvertDataRetrieverFromProviderFormat(
object dataRetrieverIn,
IEnumerable<ItemChange> changes,
out object dataRetrieverOut)
{
dataRetrieverOut = new ConvertedDataRetriever<SourceType, DestType>(dataRetrieverIn);
return true;
}
public override bool TryConvertDataRetrieverToProviderFormat(
object dataRetrieverIn,
IEnumerable<ItemChange> changes,
out object dataRetrieverOut)
{
dataRetrieverOut = new ConvertedDataRetriever<DestType, SourceType>(dataRetrieverIn);
return true;
}
Public Overloads Overrides Function TryConvertDataRetrieverFromProviderFormat(ByVal dataRetrieverIn As Object, ByVal changes As IEnumerable(Of ItemChange), ByRef dataRetrieverOut As Object) As Boolean
dataRetrieverOut = New ConvertedDataRetriever(Of SourceType, DestType)(dataRetrieverIn)
Return True
End Function
Public Overloads Overrides Function TryConvertDataRetrieverToProviderFormat(ByVal dataRetrieverIn As Object, ByVal changes As IEnumerable(Of ItemChange), ByRef dataRetrieverOut As Object) As Boolean
dataRetrieverOut = New ConvertedDataRetriever(Of DestType, SourceType)(dataRetrieverIn)
Return True
End Function
다음 코드 예제에서는 ConvertedDataRetriever
클래스를 만들고 LoadChangeData
메서드 및 IdFormats
속성을 정의합니다. 데이터 검색자를 변환할 때 데이터 변환에 필요한 모든 코드가 LoadChangeData
메서드에 포함되어 있거나 호출되어야 합니다.
public class ConvertedDataRetriever<SourceType, DestType> : IChangeDataRetriever
where SourceType : IDataObject, new()
where DestType : IDataObject, new()
{
public ConvertedDataRetriever(object dataRetriever)
{
this.dataRetriever = dataRetriever;
}
public SyncIdFormatGroup IdFormats
{
get
{
return ((IChangeDataRetriever)dataRetriever).IdFormats;
}
}
public object LoadChangeData(LoadChangeContext loadChangeContext)
{
IChangeDataRetriever iRetriever = (IChangeDataRetriever)dataRetriever;
object tempData = iRetriever.LoadChangeData(loadChangeContext);
if (tempData != null)
{
return ConvertData(tempData);
}
return null;
}
private object ConvertData(object itemData)
{
SourceType dataObj = (SourceType)itemData;
DestType returnData = new DestType();
returnData.Data = dataObj.Data;
return returnData;
}
object dataRetriever;
}
Public Class ConvertedDataRetriever(Of SourceType As {IDataObject, New}, DestType As {IDataObject, New})
Implements IChangeDataRetriever
Public Sub New(ByVal dataRetriever As Object)
Me.dataRetriever = dataRetriever
End Sub
Public ReadOnly Property IdFormats() As SyncIdFormatGroup
Get
Return DirectCast(dataRetriever, IChangeDataRetriever).IdFormats
End Get
End Property
Public Function LoadChangeData(ByVal loadChangeContext As LoadChangeContext) As Object
Dim iRetriever As IChangeDataRetriever = DirectCast(dataRetriever, IChangeDataRetriever)
Dim tempData As Object = iRetriever.LoadChangeData(loadChangeContext)
If tempData IsNot Nothing Then
Return ConvertData(tempData)
End If
Return Nothing
End Function
Private Function ConvertData(ByVal itemData As Object) As Object
Dim dataObj As SourceType = DirectCast(itemData, SourceType)
Dim returnData As New DestType()
returnData.Data = dataObj.Data
Return returnData
End Function
Private dataRetriever As Object
End Class