65.9K
CodeProject 正在变化。 阅读更多。
Home

使用 C# 的比较和同步工具

starIconstarIcon
emptyStarIcon
starIcon
emptyStarIconemptyStarIcon

2.92/5 (5投票s)

2005 年 11 月 10 日

2分钟阅读

viewsIcon

29496

downloadIcon

627

本文介绍了一个使用 C# 编写的比较/同步工具。

引言

本文介绍了一个使用 C# 编写的比较/同步工具。该控件最初是为不同数据库(生产数据库和测试数据库)中两个表的同步而创建的。然而,我注意到它可以扩展为比较和同步任何类型的对象。文章中提供的演示用于比较和同步基于字符串的键值对。

设计

控件的结构如图所示

控件接收两种类型的集合作为输入,类型为 CompareCollection

public void DisplayCollections ( CompareCollection A, 
                                     CompareCollection B )

CompareCollection 实现 ICollection 接口,并包含类型为 CompareItem 的对象。CompareItem 类包含以下成员

private object      m_sKey;
private object      m_sValue;
private object      m_sNewKey;
private object      m_sNewValue;        
private bool        m_bWasAdded         = false;
private bool        m_bWasModified      = false;
private bool        m_bWasDeleted       = false;
private bool        m_bIsDifferentKey   = false; 
private bool        m_bIsDifferentValue = false; 
private bool        m_bIsDummy          = false;
private bool        m_bIsReadOnly       = false;

Key 是类的一个重要成员。Key 用于在 ListBox 中放置对象。例如:只有当两个 string 对象具有相同的键时,它们才会在两个 ListBox 的同一行中显示。(如果项目的数值不同,则包含这些项目的行将被突出显示。)

大多数标志都易于理解,除了 IsDifferentKeyIsDifferentValue。请注意,iCompareKeyiCompareValueCompareItemvirtual 函数,应该为适当的对象进行重写。在本例中,键和值都转换为 string 类型进行比较。

类的另一个 virtual 参数是 sDisplayString,它用于在 ListBox 中显示一个 string。大部分逻辑都集中在 LineComparatorControl 类中。主要函数是

  • DoDisplayCollections:该函数将项目放置在 ListBox
    private void DoDisplayCollections ( 
              CompareCollection oLeft, CompareCollection oRight ) {
                
         int iLeftIndex  = 0;
         int iRightIndex = 0;
         int iSyncIndex  = 0;
         while ( iLeftIndex < oLeft.Count || iRightIndex < oRight.Count ){
             // Compare 
             int iCompResult = 0;
             if ( iLeftIndex == oLeft.Count ) {
                 iCompResult = 1;
             }else if ( iRightIndex == oRight.Count ){
                 iCompResult = -1;
             }else{
                 iCompResult =  oLeft[iLeftIndex].iCompareKey(
                                 oRight[iRightIndex] );
             }
    
             // Print List Box
             if ( iCompResult < 0  ){
                 // Print Left Side Only    
                 oLeft[iLeftIndex].bDifferentKey = true;             
                 LeftListBox.Items.Insert (iSyncIndex, oLeft[iLeftIndex]);
                 RightListBox.Items.Insert (iSyncIndex,                   
                                     new CompareItem( true, true, true ) );
                 iLeftIndex++;
             }else if ( iCompResult > 0 ){
                 // Print Right Side Only 
                 oRight[iRightIndex].bDifferentKey = true;
                 RightListBox.Items.Insert (iSyncIndex,
                                            oRight[iRightIndex] );
                 LeftListBox.Items.Insert (iSyncIndex, 
                                     new CompareItem( true, true, true ) ); 
                 iRightIndex++;
             }else{
               if (oLeft[iLeftIndex].iCompareValue(oRight[iRightIndex]) != 0 ){
                  oRight[iRightIndex].bDifferentValue = true;
                  oLeft[iLeftIndex].bDifferentValue = true;
               }
               RightListBox.Items.Insert ( iSyncIndex, 
                                           oRight[iRightIndex] );
               LeftListBox.Items.Insert ( iSyncIndex, 
                                          oLeft[iLeftIndex] );
               iLeftIndex++;
               iRightIndex++;
             }   
             iSyncIndex++;
         }
    }
  • bExecuteSync:此函数用于同步项目。

    如果同步失败,该函数会弹出一个包含错误消息的消息框。为了检查是否可以进行同步,使用了一个 virtual 函数 bIsSynchronizationOk

    private bool bExecuteSync ( CompareItem oFromItem, 
        CompareItem oToItem, 
        ref string sErrorMsg ){
                
         if ( oFromItem.bDummy ){
             oToItem.bDeleted = true;                  
         }else if ( oToItem.bDummy ){
             oToItem.bAdded = true;
             oToItem.sNewKey = oFromItem.sKey;
             oToItem.sNewValue = oFromItem.sValue;
         }else {
             oToItem.bModified = true;
             oToItem.sNewKey = oFromItem.sKey;
             oToItem.sNewValue = oFromItem.sValue;
         }
         
         if ( bIsSynchronizationOk ( oToItem, ref sErrorMsg ) ){
             if ( !oToItem.bDeleted ){
                 oToItem.sKey = oToItem.sNewKey;
                 oToItem.sValue = oToItem.sNewValue;
             }
             if ( oToItem.bDeleted || oToItem.bAdded ){
                 oToItem.bDummy = false;
                 oFromItem.bDummy = false;
             }
             
             oToItem.bDifferentKey = false;
             oToItem.bDifferentValue = false;
             oFromItem.bDifferentKey = false;
             oFromItem.bDifferentValue = false;
             
             return true;
    
         }else{
             
             return false;
         }
    }

为了实现您自己更改项目的存储逻辑,您需要重写函数 LeftStoreButton_ClickRightStoreButton_Click

希望本文对您有所帮助。

参考文献

为了突出显示 ListBox 中的行,我使用了文章:A C# ColorListBox

© . All rights reserved.