Introduction to the .NET Assembly

The Merge .NET assembly makes text comparison and reporting capabilities available to applications that do not need to present the Merge graphical user interface to users. For example, a web server application might use the .NET assembly to compare text or generate HTML comparison reports.

The .NET assembly can be used conveniently from any programming language that supports .NET, such as C#, Visual Basic, F#, etc.

Capabilities and limitations

The .NET assembly provides the ability to perform text comparisons upon either two or three files or strings. Comparison results can be accessed programmatically. Several types of text comparison report can also be generated.

Folder, image and binary comparisons are not supported by the assembly. Neither are Virtual File System (VFS) Plugins.

Given the aforementioned constraints, the Merge Automation API or command-line utility will be more suitable if you need to do any of the following:

  • present the Merge user interface to users;
  • integrate Merge with an application that does not support .NET;
  • use Merge capabilities not supported by the .NET assembly.

Licensing

The End-User Licence Agreement for Araxis Merge Software has specific provision for both desktop use and for Merge to be deployed as a component of a server application that provides services to multiple users. In summary, deployment as a server component requires the purchase of two Merge licences rather than the one needed for normal desktop use, though you are referred to the full EULA for the definitive terms.

Getting started with the .NET assembly in Visual Studio

Information These instructions have been prepared using Visual Studio Community 2022 for Windows Desktop. They should also be broadly applicable to other editions of Visual Studio.

Adding a reference to the Merge .NET assembly to your project

Before using the Merge .NET assembly, you need to add a reference to it to your Visual Studio project.

Information These steps are for projects that target .NET 6 and later. The older Merge .NET assembly (araxis.merge.foundation.net.dll) for use with earlier .NET frameworks is now deprecated.

  • From the Visual Studio Solution Explorer, right-click your project and select AddProject Reference…
  • Click Browse…
  • Select the Merge .NET assembly DLL named araxis.merge.foundation.net6.dll from the Merge installation directory (typically C:\Program File\Araxis\Araxis Merge).
  • Click Add. araxis.merge.foundation.net6.dll should now be listed in the Reference Manager dialog.
  • Ensure that the checkbox next to the DLL is checked and click OK.
  • Your project should now have a reference to the Merge .NET assembly.

Viewing the Merge .NET assembly documentation

  • Having added the Merge .NET assembly reference to your project, select the Visual Studio ViewObject Browser menu item.
  • The Object Browser panel appears, from which you can view documentation for the Merge .NET assembly.

Using the .NET assembly

As a supplement to the reference documentation provided in the Merge .NET assembly itself (see above), the examples below give a basic introduction to its use with the C# programming language.

Importing the .NET assembly into your code

Once your project has a reference to the Merge .NET assembly, you can import it into your code in the usual way:

using Araxis.Merge.Foundation;

Preparing comparison options

Prior to performing a text comparison, a ComparisonOptions object must be created. This has a number of properties that can be adjusted to determine how the comparison will be performed.

In the following code fragment, a ComparisonOptions object is created and several of its properties are changed from their defaults. Note that some properties (e.g. CompareWhiteSpace) expect values defined by one of the assembly’s enumerations.

var options = new ComparisonOptions();
options.CollapsedContext = 2;
options.CollapseUnchangedBlocks = true;
options.CompareLineEndings = true;
options.CompareWhiteSpace =
    WhiteSpaceOptions.TreatWhitespaceRunsAsSingleSpace;
options.ReformatXml = true;
options.ShowLineEndings = true;
options.ShowLineNumbers = false;

Comparing text

Text comparisons are performed using the TextComparison object. It provides two static comparison methods: one accepting strings containing the fully qualified paths of the files to be compared; the other accepting strings containing the textual content to be compared. Both require a ComparisonOptions object as described above.

Comparing text files

The following fragment compares two files encoded with the UTF-8 character encoding:

TextComparisonResults results = TextComparison.CompareFiles(
    options,
    "C:\\MyFolder\\File1.txt",
    Encoding.UTF8,
    "C:\\MyFolder\\File2.txt",
    Encoding.UTF8);

Comparing strings

This example shows how to compare three strings.

TextComparisonResults results = TextComparison.CompareText(
    options, buffer1, buffer2, buffer3);

Monitoring the progress of a comparison

As of Merge 2013.4287, the progress of a comparison may be monitored by providing an event handler for comparison ProgressChanged events. The event handler is specified using the ComparisonOptions object, as shown in the code fragment below. The PercentComplete property of the ProgressChangedEventArgs object passed to the event handler indicates the percentage of lines that have been compared. The Operation property is an informational string provided for debugging purposes only.

static void ProgressChangedEventHandler(
    object sender,
    ProgressChangedEventArgs e)
{
    System.Console.WriteLine(
        string.Format(
            "{0}%: {1}", e.PercentComplete, e.Operation));
}

var options = new ComparisonOptions();
options.ProgressChanged += ProgressChangedEventHandler;

Accessing the comparison results

Both CompareFiles and CompareText return a new TextComparisonResults object. This results object offers extensive information about the comparison performed.

In a three-way comparison, results are provided for comparisons between the left and middle buffers (FirstBufferPair), and the middle and right buffers (SecondBufferPair). For consistency, the results of a two-way comparison are deemed to be of the FirstBufferPair, even though there is no second buffer pair involved.

Summary information

The next example shows how to output summary comparison information for a three-way comparison.

Note that if the ComparisonOptions object has the ReformatXml property set to true, any errors in the XML reformatting will be stored in the ReformattingErrors property.

System.Console.WriteLine(
    string.Format(
        "Reformatting errors: {0}",
        results.ReformattingErrors.Length == 0 ?
            "None" : results.ReformattingErrors));
System.Console.WriteLine(
    string.Format(
        "Buffers 1 & 2 differ? {0}",
        results.FirstBufferPair.HasChanges));
System.Console.WriteLine(
    string.Format(
        "Buffers 2 & 3 differ? {0}",
        results.SecondBufferPair.HasChanges));

Understanding associations

A collection of Association objects details the changes between the two buffers of a compared pair of buffers.

Each Association object relates a range of lines in the left buffer of a comparison pair to a range of lines in the corresponding right buffer.

Association objects also have a State property that indicates whether the association represents unchanged, changed, inserted or removed text. For unchanged text, the left and right line ranges will contain the same number of lines; for changed text, the left and right line ranges may differ in length; for removed text, the right line range will be of zero length; and for inserted text the left line range will be of zero length.

The following code fragment demonstrates how to iterate over the Association objects relating the left and right buffers of a two-way text comparison (or the left and middle buffers of a three-way comparison).

System.Console.WriteLine("Changes between buffers 1 & 2:");
foreach (var association in results.FirstBufferPair.Associations)
{
    System.Console.WriteLine(
        string.Format("Lines {0}-{1} -> lines {2}-{3} [{4}]",
        1 + association.LeftBegin,
        1 + association.LeftEnd,
        1 + association.RightBegin,
        1 + association.RightEnd,
        association.State));
}

The following code iterates over every line of the left buffer, outputting their states (unchanged, changed, inserted or removed).

System.Console.WriteLine(
    "Line states for the left buffer of the first buffer pair:");
for (
    int i = 0;
    i < results.FirstBufferPair.LeftLineStates.Length;
    i++)
{
    System.Console.WriteLine(
        "Line {0} is {1}",
        i + 1,
        results.FirstBufferPair.LeftLineStates[i]);
}

Accessing lines of compared text

The TextComparisonResults object provides access to the full text of the buffers compared.

The following example demonstrates how to access a numbered line in one of the buffers. Note that this function takes a 1-based line number, whereas the Merge .NET assembly itself works with 0-based line numbers.

private static void OutputLine(
    TextComparisonResults results,
    int line,
    int bufferNumber)
{
    System.Console.WriteLine(
        string.Format(
            "Text of line {0} in buffer {1} is: {2}",
            line,
            bufferNumber + 1,
            results.Buffer(bufferNumber).Substring(
                results.Lines(bufferNumber)[line - 1]
                    .OffsetInBuffer,
                results.Lines(bufferNumber)[line - 1]
                    .LengthWithoutEndOfLineCharacters)));
}

Accessing inline changes

As of Merge 2017.4929, text comparisons made with the CompareWithinLines option set to InlineChangeType.Detailed or InlineChangeType.Simple will calculate inline changes for changed blocks of text. The FirstBufferPair and SecondBufferPair members of the TextComparisonResults object each themselves have two members (LeftInlineChanges and RightInlineChanges) that are arrays of InlineChanges, one array element for each line of the compared files or text buffers.

Information Inline changes are calculated only for lines within the ranges covered by change associations; an element for a line within the LeftInlineChanges or RightInlineChanges arrays will be null if the line belongs to an association representing an insertion, removal, or unchanged block.

The following example demonstrates how to output inline changes for a three-way text comparison. Change associations from the Associations collection are processed to output inline change details. Further information about the InlineChanges type can be found within the Merge .NET assembly documentation.

private static void OutputAllInlineChanges(TextComparisonResults results)
{
  System.Console.WriteLine("Inline changes between first and second files/buffers");
  OutputInlineChanges(results.FirstBufferPair);
  System.Console.WriteLine("Inline changes between second and third files/buffers");
  OutputInlineChanges(results.SecondBufferPair);
}

private static void OutputInlineChanges(BufferPair bufferPair)
{
  foreach (var association in bufferPair.Associations)
  {
    // only process the lines of change blocks that have been changed
    if (association.State == ChangeState.Changed)
    {
      for (var line = association.LeftBegin; line != association.LeftEnd; ++line)
      {
        System.Console.WriteLine(string.Format("[Left line {0}] {1}", line + 1, bufferPair.LeftInlineChanges[line]));
      }
      for (var line = association.RightBegin; line != association.RightEnd; ++line)
      {
        System.Console.WriteLine(string.Format("[Right line {0}] {1}", line + 1, bufferPair.RightInlineChanges[line]));
      }
    }
  }
}

Generating comparison reports

TextComparisonResults objects offer the ability to generate reports of the comparison results they represent. The following report types are available: HTML, XML, UNIX diff Edit Script, UNIX diff Context, and UNIX diff Unified. For more information about text comparison reports, see Creating a File Comparison Report.

The following code fragment generates an HTML report, encoded with UTF-8 character encoding, saving it to a file whose fully qualified path is provided.

results.Report(
    "C:\\MyFolder\\MyReport.html",
    Encoding.UTF8,
    ReportType.Html);

The next example generates a UNIX diff Unified report. The file paths contained within the report are expressly set. Note that file paths are set automatically in the results object if it is generated using the CompareFile method, but not if CompareText is used as is the case here.

TextComparisonResults results = TextComparison.CompareText(
    options, buffer1, buffer2);
results.SetFilePath(0, "C:\\MyFolder\\File1.txt");
results.SetFilePath(1, "C:\\MyFolder\\File2.txt");
results.Report(
    "C:\\MyFolder\\MyUnifiedDiff.txt",
    Encoding.ASCII,
    ReportType.DiffUnified);

Character-level comparison of strings

Character-level comparison of strings is possible using the StringComparison object:

string str1 = "My first string ABC";
string str2 = "My second string A!C";
var options = new StringComparisonOptions();
var results = StringComparison.CompareStrings(options, str1, str2);
System.Console.WriteLine(results);

Support

If you have a question not answered above or in the Merge .NET assembly’s reference documentation, please feel free to contact Araxis.