我将提供一个完整的COM模拟器C#实现,包括服务器端、客户端和测试用例,并用详细解释。

using System;
using System.Runtime.InteropServices;
using System.Threading;

// COM 接口定义
[ComVisible(true)]
[Guid("9E5E5F1A-2F3A-4B7C-A4C3-4D7E8F9B3C2D")]
[InterfaceType(ComInterfaceType.InterfaceIsIDispatch)]
public interface IComSimulator
{
    string GetData(int id);
    void SetData(int id, string value);
    double Calculate(double a, double b);
}

// COM 实现类
[ComVisible(true)]
[Guid("7A2B3C4D-5E6F-7A8B-9C0D-1E2F3A4B5C6D")]
[ClassInterface(ClassInterfaceType.None)]
[ProgId("ComSimulator.Simulator")]
public class ComSimulator : IComSimulator
{
    private readonly Dictionary<int, string> dataStore;

    public ComSimulator()
    {
        dataStore = new Dictionary<int, string>();
        Console.WriteLine("COM Simulator 初始化完成");
    }

    public string GetData(int id)
    {
        return dataStore.ContainsKey(id) ? dataStore[id] : "未找到数据";
    }

    public void SetData(int id, string value)
    {
        dataStore[id] = value;
        Console.WriteLine($"数据设置: ID={id}, Value={value}");
    }

    public double Calculate(double a, double b)
    {
        return a + b;
    }
}

// COM 服务器程序
class ComServer
{
    static void Main(string[] args)
    {
        try
        {
            // 注册COM组件
            RegistrationServices regService = new RegistrationServices();
            regService.RegisterAssembly(typeof(ComSimulator).Assembly, AssemblyRegistrationFlags.SetCodeBase);

            Console.WriteLine("COM 服务器已启动,按 Ctrl+C 退出...");
            // 保持服务器运行
            ManualResetEvent mre = new ManualResetEvent(false);
            mre.WaitOne();
        }
        catch (Exception ex)
        {
            Console.WriteLine($"错误: {ex.Message}");
        }
    }
}

// 客户端测试程序
class ComClient
{
    static void Main(string[] args)
    {
        try
        {
            // 创建COM对象
            Type comType = Type.GetTypeFromProgID("ComSimulator.Simulator");
            if (comType == null)
            {
                Console.WriteLine("无法找到COM组件");
                return;
            }

            dynamic comObject = Activator.CreateInstance(comType);
            
            // 测试用例1: 设置和获取数据
            Console.WriteLine("测试用例1: 设置和获取数据");
            comObject.SetData(1, "测试数据");
            string result = comObject.GetData(1);
            Console.WriteLine($"获取数据结果: {result}");

            // 测试用例2: 计算
            Console.WriteLine("\n测试用例2: 计算");
            double calcResult = comObject.Calculate(5.5, 3.3);
            Console.WriteLine($"计算结果: 5.5 + 3.3 = {calcResult}");

            // 测试用例3: 获取不存在的数据
            Console.WriteLine("\n测试用例3: 获取不存在的数据");
            string noData = comObject.GetData(999);
            Console.WriteLine($"获取不存在的数据结果: {noData}");
        }
        catch (Exception ex)
        {
            Console.WriteLine($"客户端错误: {ex.Message}");
        }
    }
}

解释代码结构

  1. COM接口定义 (IComSimulator):
    • 使用 [ComVisible(true)] 标记为COM可见
    • [Guid] 指定唯一标识符
    • [InterfaceType(ComInterfaceType.InterfaceIsIDispatch)] 指定接口类型为IDispatch,支持晚绑定
    • 定义三个方法:GetData、SetData 和 Calculate
  2. COM实现类 (ComSimulator):
    • 实现 IComSimulator 接口
    • 使用字典存储数据
    • 实现数据的存取和简单计算功能
    • 使用 [ProgId] 指定程序ID,便于客户端访问
  3. COM服务器 (ComServer):
    • 注册COM组件
    • 保持服务器运行状态
  4. 客户端测试程序 (ComClient):
    • 通过ProgID创建COM对象
    • 包含三个测试用例,验证功能

使用步骤

  1. 编译和注册:
    • 编译代码为EXE或DLL
    • 以管理员权限运行服务器程序进行COM注册
    • 或者使用 regasm 工具注册:regasm ComSimulator.dll /codebase
  2. 运行测试:
    • 先运行服务器程序
    • 另开一个控制台运行客户端程序

测试用例说明

  1. 测试用例1: 验证数据存储和读取功能
    • 设置ID=1的数据为"测试数据"
    • 读取ID=1的数据,预期返回"测试数据"
  2. 测试用例2: 验证计算功能
    • 调用Calculate方法,传入5.5和3.3
    • 预期返回8.8
  3. 测试用例3: 验证异常情况处理
    • 尝试读取不存在的ID=999的数据
    • 预期返回"未找到数据"

注意事项

  1. 需要在项目中启用COM互操作
  2. 运行时需要管理员权限进行注册
  3. 确保.NET Framework支持(建议使用.NET Framework 4.8或更高版本)
  4. 客户端和服务器需在同一机器上运行,或配置DCOM进行远程访问

输出示例服务器端:

COM Simulator 初始化完成
COM 服务器已启动,按 Ctrl+C 退出...
数据设置: ID=1, Value=测试数据

客户端:

测试用例1: 设置和获取数据
获取数据结果: 测试数据

测试用例2: 计算
计算结果: 5.5 + 3.3 = 8.8

测试用例3: 获取不存在的数据
获取不存在的数据结果: 未找到数据

这个实现展示了基本的COM组件开发和使用方式,可根据实际需求扩展功能。

更多推荐