From a26d8561f173e24d1130d9b0af6e196528699ab2 Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Mon, 15 Sep 2025 03:52:14 +0000 Subject: [PATCH] Migrate MEF calculator from VB.NET to C# - Convert SimpleCalculator2 console application from VB.NET to C# - Convert MefCalculator interfaces library with ICalculator, IOperation, IOperationData - Convert ExtendedOperations library with Modulo operation - Update target frameworks to .NET 8.0 for compatibility - Preserve MEF composition and extensibility architecture - Maintain same functionality: addition, subtraction, modulo operations - Interactive console loop works identically to VB.NET version Co-Authored-By: Anke Hao --- .../ExtendedOperations.csproj | 26 ++++ .../cs/ExtendedOperations/Modulo.cs | 12 ++ .../cs/MefCalculator/MefCalculator.csproj | 16 +++ .../MefCalculator/MefCalculatorInterfaces.cs | 39 ++++++ mef/simple-calculator/cs/Program.cs | 111 ++++++++++++++++++ .../cs/SimpleCalculator2.csproj | 46 ++++++++ .../cs/SimpleCalculator2.sln | 40 +++++++ 7 files changed, 290 insertions(+) create mode 100644 mef/simple-calculator/cs/ExtendedOperations/ExtendedOperations.csproj create mode 100644 mef/simple-calculator/cs/ExtendedOperations/Modulo.cs create mode 100644 mef/simple-calculator/cs/MefCalculator/MefCalculator.csproj create mode 100644 mef/simple-calculator/cs/MefCalculator/MefCalculatorInterfaces.cs create mode 100644 mef/simple-calculator/cs/Program.cs create mode 100644 mef/simple-calculator/cs/SimpleCalculator2.csproj create mode 100644 mef/simple-calculator/cs/SimpleCalculator2.sln diff --git a/mef/simple-calculator/cs/ExtendedOperations/ExtendedOperations.csproj b/mef/simple-calculator/cs/ExtendedOperations/ExtendedOperations.csproj new file mode 100644 index 00000000000..b211a213b7a --- /dev/null +++ b/mef/simple-calculator/cs/ExtendedOperations/ExtendedOperations.csproj @@ -0,0 +1,26 @@ + + + + ExtendedOperations + net8.0 + + + + ..\bin\Release\Extensions\ + + + + ..\bin\Debug\Extensions\ + + + + + false + + + + + false + + + diff --git a/mef/simple-calculator/cs/ExtendedOperations/Modulo.cs b/mef/simple-calculator/cs/ExtendedOperations/Modulo.cs new file mode 100644 index 00000000000..19c79685f73 --- /dev/null +++ b/mef/simple-calculator/cs/ExtendedOperations/Modulo.cs @@ -0,0 +1,12 @@ +using System.ComponentModel.Composition; +using MefCalculator; + +[Export(typeof(IOperation))] +[ExportMetadata("Symbol", '%')] +public class Modulo : IOperation +{ + public int Operate(int left, int right) + { + return left % right; + } +} diff --git a/mef/simple-calculator/cs/MefCalculator/MefCalculator.csproj b/mef/simple-calculator/cs/MefCalculator/MefCalculator.csproj new file mode 100644 index 00000000000..333c34efafb --- /dev/null +++ b/mef/simple-calculator/cs/MefCalculator/MefCalculator.csproj @@ -0,0 +1,16 @@ + + + + MefCalculator + net8.0 + + + + + + + + false + + + diff --git a/mef/simple-calculator/cs/MefCalculator/MefCalculatorInterfaces.cs b/mef/simple-calculator/cs/MefCalculator/MefCalculatorInterfaces.cs new file mode 100644 index 00000000000..934cf29bd76 --- /dev/null +++ b/mef/simple-calculator/cs/MefCalculator/MefCalculatorInterfaces.cs @@ -0,0 +1,39 @@ +using System.ComponentModel.Composition; + +namespace MefCalculator +{ + public interface ICalculator + { + string Calculate(string input); + } + + public interface IOperation + { + int Operate(int left, int right); + } + + public interface IOperationData + { + char Symbol { get; } + } + + [Export(typeof(IOperation))] + [ExportMetadata("Symbol", '+')] + public class Add : IOperation + { + public int Operate(int left, int right) + { + return left + right; + } + } + + [Export(typeof(IOperation))] + [ExportMetadata("Symbol", '-')] + public class Subtract : IOperation + { + public int Operate(int left, int right) + { + return left - right; + } + } +} diff --git a/mef/simple-calculator/cs/Program.cs b/mef/simple-calculator/cs/Program.cs new file mode 100644 index 00000000000..9076f536345 --- /dev/null +++ b/mef/simple-calculator/cs/Program.cs @@ -0,0 +1,111 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel.Composition; +using System.ComponentModel.Composition.Hosting; +using System.IO; +using System.Linq; +using System.Reflection; +using MefCalculator; + +namespace SimpleCalculator2 +{ + class Program + { + private static readonly string MyApplicationPath = Assembly.GetEntryAssembly().Location; + private static readonly string MyApplicationDirectory = Path.GetDirectoryName(MyApplicationPath); + + [Export(typeof(ICalculator))] + public class MySimpleCalculator : ICalculator + { + [ImportMany] + public IEnumerable> Operations { get; set; } + + public string Calculate(string input) + { + int left, right; + char operation; + int fn = FindFirstNonDigit(input); + if (fn < 0) + { + return "Could not parse command."; + } + operation = input[fn]; + try + { + left = int.Parse(input.Substring(0, fn)); + right = int.Parse(input.Substring(fn + 1)); + } + catch (Exception) + { + return "Could not parse command."; + } + foreach (var i in Operations) + { + if (i.Metadata.Symbol == operation) + { + return i.Value.Operate(left, right).ToString(); + } + } + return "Operation not found!"; + } + + private int FindFirstNonDigit(string s) + { + for (int i = 0; i < (s?.Length ?? 0); i++) + { + if (!char.IsDigit(s[i])) return i; + } + return -1; + } + } + + private class MySimpleCalculatorComposition + { + private readonly CompositionContainer _container; + public bool HasExtensions { get; } + + [Import(typeof(ICalculator))] + public ICalculator Calculator { get; set; } + + public MySimpleCalculatorComposition() + { + var catalog = new AggregateCatalog(); + + catalog.Catalogs.Add(new AssemblyCatalog(typeof(MefCalculator.ICalculator).Assembly)); + + catalog.Catalogs.Add(new AssemblyCatalog(typeof(MySimpleCalculatorComposition).Assembly)); + + var extensionsDir = Path.Combine(MyApplicationDirectory, "Extensions"); + if (Directory.Exists(extensionsDir)) + { + catalog.Catalogs.Add(new DirectoryCatalog(extensionsDir)); + HasExtensions = true; + } + + _container = new CompositionContainer(catalog); + + try + { + _container.ComposeParts(this); + } + catch (Exception ex) + { + Console.WriteLine(ex.ToString()); + } + } + } + + static void Main(string[] args) + { + var o = new MySimpleCalculatorComposition(); + if (o.HasExtensions) Console.WriteLine("Extensions loaded."); + Console.WriteLine("Enter Command:"); + string s; + while ((s = Console.ReadLine()) != null) + { + Console.WriteLine(o.Calculator.Calculate(s)); + } + Console.WriteLine("Exited"); + } + } +} diff --git a/mef/simple-calculator/cs/SimpleCalculator2.csproj b/mef/simple-calculator/cs/SimpleCalculator2.csproj new file mode 100644 index 00000000000..ebb26c33d35 --- /dev/null +++ b/mef/simple-calculator/cs/SimpleCalculator2.csproj @@ -0,0 +1,46 @@ + + + + Exe + SimpleCalculator2 + net8.0 + SimpleCalculator2.Program + + + + bin\Release\ + + + + bin\Debug\ + + + + + + + + + + + + + + + + + + false + false + false + + + true + + + + + false + + + diff --git a/mef/simple-calculator/cs/SimpleCalculator2.sln b/mef/simple-calculator/cs/SimpleCalculator2.sln new file mode 100644 index 00000000000..dee661cf1ba --- /dev/null +++ b/mef/simple-calculator/cs/SimpleCalculator2.sln @@ -0,0 +1,40 @@ + +Microsoft Visual Studio Solution File, Format Version 12.00 +# Visual Studio Version 16 +VisualStudioVersion = 16.0.29306.81 +MinimumVisualStudioVersion = 10.0.40219.1 +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "SimpleCalculator2", "SimpleCalculator2.csproj", "{3FF19E38-FDCE-411F-9656-65B69A181A2C}" + ProjectSection(ProjectDependencies) = postProject + {6CE9704B-685C-4792-996B-EF08F704F14E} = {6CE9704B-685C-4792-996B-EF08F704F14E} + EndProjectSection +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ExtendedOperations", "ExtendedOperations\ExtendedOperations.csproj", "{6CE9704B-685C-4792-996B-EF08F704F14E}" +EndProject +Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MefCalculator", "MefCalculator\MefCalculator.csproj", "{9DF1F88B-D8F8-4D89-839F-45CB494C1A61}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Any CPU = Debug|Any CPU + Release|Any CPU = Release|Any CPU + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {3FF19E38-FDCE-411F-9656-65B69A181A2C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {3FF19E38-FDCE-411F-9656-65B69A181A2C}.Debug|Any CPU.Build.0 = Debug|Any CPU + {3FF19E38-FDCE-411F-9656-65B69A181A2C}.Release|Any CPU.ActiveCfg = Release|Any CPU + {3FF19E38-FDCE-411F-9656-65B69A181A2C}.Release|Any CPU.Build.0 = Release|Any CPU + {6CE9704B-685C-4792-996B-EF08F704F14E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {6CE9704B-685C-4792-996B-EF08F704F14E}.Debug|Any CPU.Build.0 = Debug|Any CPU + {6CE9704B-685C-4792-996B-EF08F704F14E}.Release|Any CPU.ActiveCfg = Release|Any CPU + {6CE9704B-685C-4792-996B-EF08F704F14E}.Release|Any CPU.Build.0 = Release|Any CPU + {9DF1F88B-D8F8-4D89-839F-45CB494C1A61}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {9DF1F88B-D8F8-4D89-839F-45CB494C1A61}.Debug|Any CPU.Build.0 = Debug|Any CPU + {9DF1F88B-D8F8-4D89-839F-45CB494C1A61}.Release|Any CPU.ActiveCfg = Release|Any CPU + {9DF1F88B-D8F8-4D89-839F-45CB494C1A61}.Release|Any CPU.Build.0 = Release|Any CPU + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection + GlobalSection(ExtensibilityGlobals) = postSolution + SolutionGuid = {0574C180-4EA2-4ACA-8616-AC2E4C393A99} + EndGlobalSection +EndGlobal