C# 多窗口通信实现方案

几种 C# 多窗口通信的完整实现方案,包括事件机制、消息传递、服务定位等模式。

方案一:基于事件/委托的通信 (推荐)

1. 基础事件通信模式

// EventCommunication.cs
using System;
using System.Collections.Generic;
using System.Windows.Forms;

// 1. 定义消息类
public class WindowMessage
{
    public string Sender { get; set; }
    public string Receiver { get; set; }
    public string MessageType { get; set; }
    public object Data { get; set; }
    public DateTime Timestamp { get; set; }

    public WindowMessage(string sender, string receiver, string type, object data)
    {
        Sender = sender;
        Receiver = receiver;
        MessageType = type;
        Data = data;
        Timestamp = DateTime.Now;
    }
}

// 2. 事件管理器(单例模式)
public class WindowEventManager
{
    private static WindowEventManager _instance;
    private static readonly object _lock = new object();
    
    // 定义事件委托
    public delegate void MessageReceivedHandler(WindowMessage message);
    
    // 全局消息事件
    public event MessageReceivedHandler GlobalMessageReceived;
    
    // 窗口特定消息字典
    private Dictionary<string, MessageReceivedHandler> _windowHandlers;
    
    private WindowEventManager()
    {
        _windowHandlers = new Dictionary<string, MessageReceivedHandler>();
    }
    
    public static WindowEventManager Instance
    {
        get
        {
            lock (_lock)
            {
                return _instance ?? (_instance = new WindowEventManager());
            }
        }
    }
    
    // 注册窗口消息处理器
    public void RegisterWindow(string windowName, MessageReceivedHandler handler)
    {
        if (!_windowHandlers.ContainsKey(windowName))
        {
            _windowHandlers[windowName] = handler;
        }
        else
        {
            _windowHandlers[windowName] += handler;
        }
    }
    
    // 注销窗口
    public void UnregisterWindow(string windowName, MessageReceivedHandler handler)
    {
        if (_windowHandlers.ContainsKey(windowName))
        {
            _windowHandlers[windowName] -= handler;
            if (_windowHandlers[windowName] == null)
            {
                _windowHandlers.Remove(windowName);
            }
        }
    }
    
    // 发送消息到特定窗口
    public void SendToWindow(string targetWindow, WindowMessage message)
    {
        if (_windowHandlers.ContainsKey(targetWindow))
        {
            _windowHandlers[targetWindow]?.Invoke(message);
        }
    }
    
    // 广播消息到所有窗口
    public void Broadcast(WindowMessage message)
    {
        GlobalMessageReceived?.Invoke(message);
        
        foreach (var handler in _windowHandlers.Values)
        {
            handler?.Invoke(message);
        }
    }
}

// 3. 基础窗口类
public class BaseWindow : Form
{
    protected string WindowName { get; set; }
    
    public BaseWindow(string name)
    {
        WindowName = name;
        this.Text = name;
        this.FormClosed += BaseWindow_FormClosed;
    }
    
    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);
        // 注册到事件管理器
        WindowEventManager.Instance.RegisterWindow(WindowName, HandleMessage);
        WindowEventManager.Instance.GlobalMessageReceived += HandleGlobalMessage;
    }
    
    protected virtual void HandleMessage(WindowMessage message)
    {
        // 子类重写处理特定消息
        if (message.Receiver == WindowName || message.Receiver == "ALL")
        {
            Console.WriteLine($"[{WindowName}] Received: {message.MessageType} from {message.Sender}");
        }
    }
    
    protected virtual void HandleGlobalMessage(WindowMessage message)
    {
        // 处理全局广播消息
        Console.WriteLine($"[{WindowName}] Global: {message.MessageType}");
    }
    
    protected void SendMessage(string targetWindow, string messageType, object data)
    {
        var message = new WindowMessage(WindowName, targetWindow, messageType, data);
        WindowEventManager.Instance.SendToWindow(targetWindow, message);
    }
    
    protected void BroadcastMessage(string messageType, object data)
    {
        var message = new WindowMessage(WindowName, "ALL", messageType, data);
        WindowEventManager.Instance.Broadcast(message);
    }
    
    private void BaseWindow_FormClosed(object sender, FormClosedEventArgs e)
    {
        // 注销事件
        WindowEventManager.Instance.UnregisterWindow(WindowName, HandleMessage);
        WindowEventManager.Instance.GlobalMessageReceived -= HandleGlobalMessage;
    }
}

// 4. 具体窗口实现
public class MainWindow : BaseWindow
{
    private Button btnOpenChild;
    private Button btnSendMessage;
    private TextBox txtMessage;
    private ListBox lstLog;
    private List<ChildWindow> childWindows;
    
    public MainWindow() : base("MainWindow")
    {
        InitializeComponents();
        childWindows = new List<ChildWindow>();
    }
    
    private void InitializeComponents()
    {
        this.Size = new System.Drawing.Size(600, 500);
        
        // 打开子窗口按钮
        btnOpenChild = new Button
        {
            Text = "打开子窗口",
            Location = new System.Drawing.Point(10, 10),
            Size = new System.Drawing.Size(100, 30)
        };
        btnOpenChild.Click += BtnOpenChild_Click;
        
        // 发送消息按钮
        btnSendMessage = new Button
        {
            Text = "发送消息",
            Location = new System.Drawing.Point(120, 10),
            Size = new System.Drawing.Size(100, 30)
        };
        btnSendMessage.Click += BtnSendMessage_Click;
        
        // 消息文本框
        txtMessage = new TextBox
        {
            Location = new System.Drawing.Point(230, 15),
            Size = new System.Drawing.Size(200, 20)
        };
        
        // 日志列表框
        lstLog = new ListBox
        {
            Location = new System.Drawing.Point(10, 50),
            Size = new System.Drawing.Size(560, 400)
        };
        
        this.Controls.Add(btnOpenChild);
        this.Controls.Add(btnSendMessage);
        this.Controls.Add(txtMessage);
        this.Controls.Add(lstLog);
    }
    
    private void BtnOpenChild_Click(object sender, EventArgs e)
    {
        var child = new ChildWindow($"ChildWindow{childWindows.Count + 1}");
        child.Show();
        childWindows.Add(child);
        AddLog($"创建子窗口: {child.WindowName}");
    }
    
    private void BtnSendMessage_Click(object sender, EventArgs e)
    {
        if (!string.IsNullOrEmpty(txtMessage.Text))
        {
            // 发送到所有子窗口
            BroadcastMessage("USER_MESSAGE", txtMessage.Text);
            AddLog($"广播消息: {txtMessage.Text}");
            txtMessage.Clear();
        }
    }
    
    protected override void HandleMessage(WindowMessage message)
    {
        base.HandleMessage(message);
        
        if (message.MessageType == "CHILD_RESPONSE")
        {
            AddLog($"收到响应: {message.Data} from {message.Sender}");
        }
        else if (message.MessageType == "CHILD_CLOSED")
        {
            AddLog($"子窗口关闭: {message.Sender}");
        }
    }
    
    private void AddLog(string message)
    {
        if (lstLog.InvokeRequired)
        {
            lstLog.Invoke(new Action(() => AddLog(message)));
        }
        else
        {
            lstLog.Items.Add($"[{DateTime.Now:HH:mm:ss}] {message}");
            lstLog.SelectedIndex = lstLog.Items.Count - 1;
        }
    }
}

public class ChildWindow : BaseWindow
{
    private Button btnSendToMain;
    private Button btnBroadcast;
    private TextBox txtMessage;
    private ListBox lstLog;
    
    public ChildWindow(string name) : base(name)
    {
        InitializeComponents();
    }
    
    private void InitializeComponents()
    {
        this.Size = new System.Drawing.Size(400, 300);
        
        btnSendToMain = new Button
        {
            Text = "发送到主窗口",
            Location = new System.Drawing.Point(10, 10),
            Size = new System.Drawing.Size(120, 30)
        };
        btnSendToMain.Click += BtnSendToMain_Click;
        
        btnBroadcast = new Button
        {
            Text = "广播到所有",
            Location = new System.Drawing.Point(140, 10),
            Size = new System.Drawing.Size(120, 30)
        };
        btnBroadcast.Click += BtnBroadcast_Click;
        
        txtMessage = new TextBox
        {
            Location = new System.Drawing.Point(10, 50),
            Size = new System.Drawing.Size(250, 20)
        };
        
        lstLog = new ListBox
        {
            Location = new System.Drawing.Point(10, 80),
            Size = new System.Drawing.Size(360, 180)
        };
        
        this.Controls.Add(btnSendToMain);
        this.Controls.Add(btnBroadcast);
        this.Controls.Add(txtMessage);
        this.Controls.Add(lstLog);
    }
    
    private void BtnSendToMain_Click(object sender, EventArgs e)
    {
        if (!string.IsNullOrEmpty(txtMessage.Text))
        {
            SendMessage("MainWindow", "CHILD_RESPONSE", txtMessage.Text);
            AddLog($"发送到主窗口: {txtMessage.Text}");
            txtMessage.Clear();
        }
    }
    
    private void BtnBroadcast_Click(object sender, EventArgs e)
    {
        if (!string.IsNullOrEmpty(txtMessage.Text))
        {
            BroadcastMessage("CHILD_BROADCAST", txtMessage.Text);
            AddLog($"广播消息: {txtMessage.Text}");
            txtMessage.Clear();
        }
    }
    
    protected override void HandleMessage(WindowMessage message)
    {
        base.HandleMessage(message);
        
        if (message.MessageType == "USER_MESSAGE")
        {
            AddLog($"收到主窗口消息: {message.Data}");
        }
    }
    
    protected override void HandleGlobalMessage(WindowMessage message)
    {
        base.HandleGlobalMessage(message);
        
        if (message.MessageType == "CHILD_BROADCAST" && message.Sender != WindowName)
        {
            AddLog($"收到广播: {message.Data} from {message.Sender}");
        }
    }
    
    protected override void OnFormClosed(FormClosedEventArgs e)
    {
        BroadcastMessage("CHILD_CLOSED", WindowName);
        base.OnFormClosed(e);
    }
    
    private void AddLog(string message)
    {
        if (lstLog.InvokeRequired)
        {
            lstLog.Invoke(new Action(() => AddLog(message)));
        }
        else
        {
            lstLog.Items.Add($"[{DateTime.Now:HH:mm:ss}] {message}");
            lstLog.SelectedIndex = lstLog.Items.Count - 1;
        }
    }
}

// 5. 程序入口
static class Program
{
    [STAThread]
    static void Main()
    {
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(new MainWindow());
    }
}

方案二:使用中介者模式

// MediatorCommunication.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;

// 1. 中介者接口
public interface IWindowMediator
{
    void Register(IWindowComponent component);
    void Unregister(IWindowComponent component);
    void Send(string from, string to, string message, object data);
    void Broadcast(string from, string message, object data);
}

// 2. 组件接口
public interface IWindowComponent
{
    string Name { get; }
    void Receive(string from, string message, object data);
}

// 3. 具体中介者
public class WindowMediator : IWindowMediator
{
    private Dictionary<string, IWindowComponent> _components;
    
    public WindowMediator()
    {
        _components = new Dictionary<string, IWindowComponent>();
    }
    
    public void Register(IWindowComponent component)
    {
        if (!_components.ContainsKey(component.Name))
        {
            _components[component.Name] = component;
        }
    }
    
    public void Unregister(IWindowComponent component)
    {
        _components.Remove(component.Name);
    }
    
    public void Send(string from, string to, string message, object data)
    {
        if (_components.ContainsKey(to))
        {
            _components[to].Receive(from, message, data);
        }
    }
    
    public void Broadcast(string from, string message, object data)
    {
        foreach (var component in _components.Values.Where(c => c.Name != from))
        {
            component.Receive(from, message, data);
        }
    }
    
    public List<string> GetRegisteredWindows()
    {
        return _components.Keys.ToList();
    }
}

// 4. 中介者窗口基类
public abstract class MediatorWindow : Form, IWindowComponent
{
    protected IWindowMediator Mediator { get; private set; }
    public abstract string Name { get; }
    
    public MediatorWindow(IWindowMediator mediator)
    {
        Mediator = mediator;
        this.FormClosed += (s, e) => Mediator.Unregister(this);
    }
    
    protected override void OnLoad(EventArgs e)
    {
        base.OnLoad(e);
        Mediator.Register(this);
    }
    
    public abstract void Receive(string from, string message, object data);
    
    protected void SendTo(string targetWindow, string message, object data)
    {
        Mediator.Send(Name, targetWindow, message, data);
    }
    
    protected void Broadcast(string message, object data)
    {
        Mediator.Broadcast(Name, message, data);
    }
}

// 5. 使用示例
public class MediatorMainWindow : MediatorWindow
{
    public override string Name => "MainWindow";
    private ListBox lstMessages;
    
    public MediatorMainWindow(IWindowMediator mediator) : base(mediator)
    {
        InitializeComponents();
    }
    
    private void InitializeComponents()
    {
        this.Text = "主窗口 (中介者模式)";
        this.Size = new System.Drawing.Size(500, 400);
        
        lstMessages = new ListBox
        {
            Dock = DockStyle.Fill
        };
        
        var btnOpen = new Button
        {
            Text = "打开子窗口",
            Dock = DockStyle.Top,
            Height = 30
        };
        btnOpen.Click += (s, e) =>
        {
            var child = new MediatorChildWindow(Mediator, $"Child{new Random().Next(1000)}");
            child.Show();
        };
        
        this.Controls.Add(lstMessages);
        this.Controls.Add(btnOpen);
    }
    
    public override void Receive(string from, string message, object data)
    {
        AddLog($"来自 {from}: {message} - {data}");
    }
    
    private void AddLog(string text)
    {
        if (lstMessages.InvokeRequired)
        {
            lstMessages.Invoke(new Action(() => AddLog(text)));
        }
        else
        {
            lstMessages.Items.Add($"[{DateTime.Now:HH:mm:ss}] {text}");
        }
    }
}

public class MediatorChildWindow : MediatorWindow
{
    private TextBox txtMessage;
    private string _name;
    
    public override string Name => _name;
    
    public MediatorChildWindow(IWindowMediator mediator, string name) : base(mediator)
    {
        _name = name;
        InitializeComponents();
    }
    
    private void InitializeComponents()
    {
        this.Text = _name;
        this.Size = new System.Drawing.Size(300, 200);
        
        txtMessage = new TextBox
        {
            Location = new System.Drawing.Point(10, 10),
            Size = new System.Drawing.Size(200, 20)
        };
        
        var btnSend = new Button
        {
            Text = "发送到主窗口",
            Location = new System.Drawing.Point(10, 40),
            Size = new System.Drawing.Size(120, 30)
        };
        btnSend.Click += (s, e) =>
        {
            if (!string.IsNullOrEmpty(txtMessage.Text))
            {
                SendTo("MainWindow", "CHILD_MESSAGE", txtMessage.Text);
                txtMessage.Clear();
            }
        };
        
        var btnBroadcast = new Button
        {
            Text = "广播",
            Location = new System.Drawing.Point(140, 40),
            Size = new System.Drawing.Size(120, 30)
        };
        btnBroadcast.Click += (s, e) =>
        {
            if (!string.IsNullOrEmpty(txtMessage.Text))
            {
                Broadcast("BROADCAST_MESSAGE", txtMessage.Text);
                txtMessage.Clear();
            }
        };
        
        this.Controls.Add(txtMessage);
        this.Controls.Add(btnSend);
        this.Controls.Add(btnBroadcast);
    }
    
    public override void Receive(string from, string message, object data)
    {
        // 处理接收到的消息
    }
}

方案三:使用消息队列(高级方案)

// MessageQueueCommunication.cs
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
using System.Windows.Forms;

// 1. 消息队列管理器
public class WindowMessageQueue
{
    private static WindowMessageQueue _instance;
    private static readonly object _lock = new object();
    
    // 消息队列
    private ConcurrentDictionary<string, BlockingCollection<WindowMessage>> _queues;
    private ConcurrentDictionary<string, List<Action<WindowMessage>>> _subscribers;
    
    // 后台处理线程
    private CancellationTokenSource _cancellationTokenSource;
    private List<Task> _workerTasks;
    
    private WindowMessageQueue()
    {
        _queues = new ConcurrentDictionary<string, BlockingCollection<WindowMessage>>();
        _subscribers = new ConcurrentDictionary<string, List<Action<WindowMessage>>>();
        _cancellationTokenSource = new CancellationTokenSource();
        _workerTasks = new List<Task>();
    }
    
    public static WindowMessageQueue Instance
    {
        get
        {
            lock (_lock)
            {
                return _instance ?? (_instance = new WindowMessageQueue());
            }
        }
    }
    
    // 创建窗口队列
    public void CreateQueue(string windowName)
    {
        _queues.TryAdd(windowName, new BlockingCollection<WindowMessage>());
        _subscribers.TryAdd(windowName, new List<Action<WindowMessage>>());
        
        // 启动消息处理任务
        var task = Task.Run(() => ProcessMessages(windowName), _cancellationTokenSource.Token);
        _workerTasks.Add(task);
    }
    
    // 订阅消息
    public void Subscribe(string windowName, Action<WindowMessage> handler)
    {
        if (_subscribers.ContainsKey(windowName))
        {
            _subscribers[windowName].Add(handler);
        }
    }
    
    // 发送消息
    public void SendMessage(string targetWindow, WindowMessage message)
    {
        if (_queues.ContainsKey(targetWindow))
        {
            _queues[targetWindow].Add(message);
        }
    }
    
    // 广播消息
    public void Broadcast(WindowMessage message, params string[] excludeWindows)
    {
        var excludeSet = new HashSet<string>(excludeWindows);
        
        foreach (var kvp in _queues)
        {
            if (!excludeSet.Contains(kvp.Key))
            {
                kvp.Value.Add(message);
            }
        }
    }
    
    // 处理消息
    private void ProcessMessages(string windowName)
    {
        var queue = _queues[windowName];
        var token = _cancellationTokenSource.Token;
        
        try
        {
            foreach (var message in queue.GetConsumingEnumerable(token))
            {
                if (_subscribers.ContainsKey(windowName))
                {
                    foreach (var handler in _subscribers[windowName])
                    {
                        // 在UI线程上执行
                        Application.CurrentForm?.Invoke(new Action(() =>
                        {
                            handler(message);
                        }));
                    }
                }
            }
        }
        catch (OperationCanceledException)
        {
            // 正常取消
        }
    }
    
    // 清理资源
    public void Shutdown()
    {
        _cancellationTokenSource.Cancel();
        
        Task.WhenAll(_workerTasks).Wait();
        
        foreach (var queue in _queues.Values)
        {
            queue.CompleteAdding();
            queue.Dispose();
        }
        
        _queues.Clear();
        _subscribers.Clear();
    }
}

// 扩展类,用于获取当前窗体
public static class ApplicationHelper
{
    public static Form CurrentForm { get; set; }
}

// 2. 消息队列窗口基类
public class QueueWindow : Form
{
    protected string WindowName { get; }
    
    public QueueWindow(string name)
    {
        WindowName = name;
        this.Text = name;
        
        // 注册当前窗体
        ApplicationHelper.CurrentForm = this;
        
        // 创建消息队列
        WindowMessageQueue.Instance.CreateQueue(WindowName);
        
        this.FormClosed += (s, e) =>
        {
            // 清理工作
            if (ApplicationHelper.CurrentForm == this)
            {
                ApplicationHelper.CurrentForm = null;
            }
        };
    }
    
    protected void SubscribeToMessages(Action<WindowMessage> handler)
    {
        WindowMessageQueue.Instance.Subscribe(WindowName, handler);
    }
    
    protected void SendToQueue(string targetWindow, WindowMessage message)
    {
        WindowMessageQueue.Instance.SendMessage(targetWindow, message);
    }
    
    protected void BroadcastToQueue(WindowMessage message, params string[] excludeWindows)
    {
        WindowMessageQueue.Instance.Broadcast(message, excludeWindows);
    }
}

方案四:使用WPF的MVVM模式 + 消息总线

// WPF MVVM + Message Bus
// MainWindow.xaml.cs
public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        DataContext = new MainViewModel();
        
        // 订阅消息
        MessageBus.Default.Subscribe<string>(this, "StatusUpdate", OnStatusUpdate);
        MessageBus.Default.Subscribe<DataMessage>(this, "DataChanged", OnDataChanged);
    }
    
    private void OnStatusUpdate(string status)
    {
        // 更新UI
        Dispatcher.Invoke(() =>
        {
            txtStatus.Text = status;
        });
    }
    
    private void OnDataChanged(DataMessage data)
    {
        // 处理数据变化
        Dispatcher.Invoke(() =>
        {
            // 更新数据绑定
        });
    }
    
    private void OpenChildWindow_Click(object sender, RoutedEventArgs e)
    {
        var childWindow = new ChildWindow();
        childWindow.Owner = this;
        childWindow.Show();
    }
    
    protected override void OnClosed(EventArgs e)
    {
        // 取消订阅
        MessageBus.Default.Unsubscribe(this);
        base.OnClosed(e);
    }
}

// MainViewModel.cs
public class MainViewModel : INotifyPropertyChanged
{
    private ObservableCollection<string> _messages;
    
    public ObservableCollection<string> Messages
    {
        get => _messages;
        set
        {
            _messages = value;
            OnPropertyChanged();
        }
    }
    
    public ICommand SendMessageCommand { get; }
    
    public MainViewModel()
    {
        Messages = new ObservableCollection<string>();
        SendMessageCommand = new RelayCommand(SendMessage);
        
        // 订阅全局消息
        MessageBus.Default.Subscribe<WindowMessage>(this, "AnyMessage", OnMessageReceived);
    }
    
    private void SendMessage()
    {
        // 发送消息到所有窗口
        MessageBus.Default.Publish("GlobalMessage", "Hello from Main Window!");
    }
    
    private void OnMessageReceived(WindowMessage message)
    {
        Messages.Add($"[{message.Sender}] {message.Content}");
    }
    
    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

// MessageBus.cs (简单的消息总线实现)
public class MessageBus
{
    private static MessageBus _instance;
    public static MessageBus Default => _instance ??= new MessageBus();
    
    private readonly Dictionary<string, List<WeakReference>> _subscribers;
    private readonly object _lock = new object();
    
    private MessageBus()
    {
        _subscribers = new Dictionary<string, List<WeakReference>>();
    }
    
    public void Subscribe<T>(object subscriber, string message, Action<T> handler)
    {
        lock (_lock)
        {
            if (!_subscribers.ContainsKey(message))
            {
                _subscribers[message] = new List<WeakReference>();
            }
            
            var handlerWrapper = new HandlerWrapper<T>(handler);
            _subscribers[message].Add(new WeakReference(subscriber));
        }
    }
    
    public void Publish<T>(string message, T data)
    {
        lock (_lock)
        {
            if (_subscribers.ContainsKey(message))
            {
                foreach (var reference in _subscribers[message].ToList())
                {
                    if (reference.IsAlive && reference.Target is Action<T> handler)
                    {
                        try
                        {
                            handler(data);
                        }
                        catch (Exception ex)
                        {
                            // 处理异常
                        }
                    }
                }
            }
        }
    }
    
    public void Unsubscribe(object subscriber)
    {
        lock (_lock)
        {
            foreach (var message in _subscribers.Keys.ToList())
            {
                _subscribers[message].RemoveAll(r => !r.IsAlive || r.Target == subscriber);
            }
        }
    }
    
    private class HandlerWrapper<T>
    {
        private readonly Action<T> _handler;
        
        public HandlerWrapper(Action<T> handler)
        {
            _handler = handler;
        }
        
        public static implicit operator Action<T>(HandlerWrapper<T> wrapper)
        {
            return wrapper._handler;
        }
    }
}

方案五:使用.NET Core的依赖注入和事件总线

// Startup.cs (ASP.NET Core风格)
public class Startup
{
    public void ConfigureServices(IServiceCollection services)
    {
        // 注册窗口服务
        services.AddSingleton<IWindowManager, WindowManager>();
        services.AddSingleton<IEventAggregator, EventAggregator>();
        
        // 注册窗口
        services.AddTransient<MainWindow>();
        services.AddTransient<ChildWindow>();
        services.AddTransient<SettingsWindow>();
        
        // 注册事件处理器
        services.AddTransient<IEventHandler<UserLoggedInEvent>, UserEventHandler>();
        services.AddTransient<IEventHandler<DataUpdatedEvent>, DataEventHandler>();
    }
}

// WindowManager.cs
public interface IWindowManager
{
    void ShowWindow<T>() where T : Form;
    void SendMessage(string windowName, object message);
    void RegisterWindow(string name, Form window);
    void UnregisterWindow(string name);
}

public class WindowManager : IWindowManager
{
    private readonly Dictionary<string, Form> _windows;
    private readonly IEventAggregator _eventAggregator;
    
    public WindowManager(IEventAggregator eventAggregator)
    {
        _windows = new Dictionary<string, Form>();
        _eventAggregator = eventAggregator;
    }
    
    public void ShowWindow<T>() where T : Form
    {
        var form = ActivatorUtilities.CreateInstance<T>(ServiceProvider);
        form.Show();
        RegisterWindow(form.Name, form);
    }
    
    public void SendMessage(string windowName, object message)
    {
        if (_windows.ContainsKey(windowName))
        {
            var window = _windows[windowName];
            if (window is IMessageReceiver receiver)
            {
                receiver.ReceiveMessage(message);
            }
        }
    }
    
    public void RegisterWindow(string name, Form window)
    {
        _windows[name] = window;
        window.FormClosed += (s, e) => UnregisterWindow(name);
    }
    
    public void UnregisterWindow(string name)
    {
        _windows.Remove(name);
    }
    
    // 通过事件聚合器发布事件
    public void PublishEvent<TEvent>(TEvent @event) where TEvent : IEvent
    {
        _eventAggregator.Publish(@event);
    }
}

// EventAggregator.cs
public interface IEventAggregator
{
    void Subscribe<TEvent>(IEventHandler<TEvent> handler) where TEvent : IEvent;
    void Unsubscribe<TEvent>(IEventHandler<TEvent> handler) where TEvent : IEvent;
    void Publish<TEvent>(TEvent @event) where TEvent : IEvent;
}

public class EventAggregator : IEventAggregator
{
    private readonly Dictionary<Type, List<object>> _handlers;
    
    public EventAggregator()
    {
        _handlers = new Dictionary<Type, List<object>>();
    }
    
    public void Subscribe<TEvent>(IEventHandler<TEvent> handler) where TEvent : IEvent
    {
        var eventType = typeof(TEvent);
        if (!_handlers.ContainsKey(eventType))
        {
            _handlers[eventType] = new List<object>();
        }
        _handlers[eventType].Add(handler);
    }
    
    public void Publish<TEvent>(TEvent @event) where TEvent : IEvent
    {
        var eventType = typeof(TEvent);
        if (_handlers.ContainsKey(eventType))
        {
            foreach (var handler in _handlers[eventType])
            {
                ((IEventHandler<TEvent>)handler).Handle(@event);
            }
        }
    }
    
    public void Unsubscribe<TEvent>(IEventHandler<TEvent> handler) where TEvent : IEvent
    {
        var eventType = typeof(TEvent);
        if (_handlers.ContainsKey(eventType))
        {
            _handlers[eventType].Remove(handler);
        }
    }
}

使用示例和测试

// Program.cs - 测试代码
class Program
{
    [STAThread]
    static void Main()
    {
        // 测试方案一:事件通信
        TestEventCommunication();
        
        // 测试方案二:中介者模式
        TestMediatorPattern();
        
        // 测试方案三:消息队列
        TestMessageQueue();
    }
    
    static void TestEventCommunication()
    {
        Console.WriteLine("=== 测试事件通信模式 ===");
        
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        
        var mainWindow = new MainWindow();
        
        // 启动应用
        Application.Run(mainWindow);
    }
    
    static void TestMediatorPattern()
    {
        Console.WriteLine("=== 测试中介者模式 ===");
        
        var mediator = new WindowMediator();
        var mainWindow = new MediatorMainWindow(mediator);
        
        Application.EnableVisualStyles();
        Application.SetCompatibleTextRenderingDefault(false);
        Application.Run(mainWindow);
    }
    
    static void TestMessageQueue()
    {
        Console.WriteLine("=== 测试消息队列 ===");
        
        // 创建并启动窗口
        var window1 = new QueueWindow("Window1");
        var window2 = new QueueWindow("Window2");
        
        window1.SubscribeToMessages(msg =>
        {
            Console.WriteLine($"Window1收到: {msg.MessageType} from {msg.Sender}");
        });
        
        window2.SubscribeToMessages(msg =>
        {
            Console.WriteLine($"Window2收到: {msg.MessageType} from {msg.Sender}");
        });
        
        // 发送测试消息
        var testMessage = new WindowMessage("System", "Window1", "TEST", "Hello");
        WindowMessageQueue.Instance.SendMessage("Window1", testMessage);
        
        // 注意:实际使用时需要创建Form并运行Application
    }
}

参考代码 C#实现的多窗口互相通信 www.3dddown.com/cnb/122448.html

比较总结

方案 优点 缺点 适用场景
事件/委托 简单直观,.NET原生支持 强耦合,需要管理事件订阅 小型应用,窗口数量少
中介者模式 解耦,集中管理 中介者可能成为瓶颈 中型应用,需要集中控制
消息队列 异步处理,高并发 实现复杂,需要管理线程 大型应用,高并发需求
消息总线 松耦合,易于扩展 需要额外框架支持 MVVM应用,WPF项目
依赖注入 可测试,松耦合 配置复杂,学习成本高 企业级应用,需要高可测试性

最佳实践建议

  1. 小型项目:使用事件/委托方案一,简单高效
  2. 中型项目:使用中介者模式或消息总线,平衡复杂度与功能
  3. 大型项目:使用消息队列或依赖注入,确保可扩展性和可维护性
  4. WPF项目:优先使用MVVM + 消息总线方案
  5. 跨线程通信:务必使用Control.Invoke或Dispatcher.Invoke更新UI
posted @ 2026-01-23 16:46  yes_go  阅读(0)  评论(0)    收藏  举报