C#多EXE共用单例ZoneManager类的实现与使用咨询
关于ZoneManager单例实现与WCF调用的问题
我实现了一个ZoneManager类,用于跟踪机器中运动部件(机械臂、门等)占用的物理空间,并将其封装为可插拔DLL。由于缺乏单例模式的实践经验,有以下疑问:
- 当前代码是否正确实现了单例模式?
- 在EXE中如何调用其功能?是否不能像普通类那样实例化?
- 该类需通过WCF被其他PC的第三方程序调用,如何确保所有调用指向同一实例?
当前实现代码
namespace Mechanical_Interactions { public sealed class ZoneManager { private static readonly ZoneManager instance = new ZoneManager(); private ZoneManager() { //读取XML文件到两个可枚举列表:users和content,分别代表所有位置,以及所有可能申请区域访问权限的资源列表,用于在运动前避免碰撞和冲突 } public static ZoneManager getManager() { return instance; } public IEnumerable<Content> periodicals{get;} public IEnumerable<Users> users{get;} public bool requestAccess(string zone,string resource) { //互斥锁保护,检查区域是否被其他资源占用,若是则返回false;若未被占用,则将resourceID设为区域对象的所有者并返回true } public void returnContent(string title, string resource) { //确认释放权限的资源是最初获取权限的资源,若是则释放权限标记。失败无关紧要,因为下次requestAccess会返回false,可在该处处理 } private object Mutex {get;} = new object(); } public static class Zone { //string ID //string currentOwner } public class Resource { //string ID //List<Zone> InUseZones{get;} } }
问题解答
1. 当前代码是否正确实现了单例模式?
你的代码基本实现了线程安全的饿汉式单例,满足单例的核心要求:
- 类标记为
sealed,防止子类继承破坏单例特性 - 构造函数私有,外部无法直接实例化
- 静态只读实例在程序启动时初始化,全程仅存在一个实例
有两处可优化的细节:
- 遵循C#命名规范,将静态获取方法改为
GetManager(首字母大写) - 可以直接把
instance设为public static readonly,去掉getManager()方法,外部通过ZoneManager.Instance访问更符合C#开发习惯
2. 在EXE中如何调用其功能?是否不能像普通类那样实例化?
没错,不能用new ZoneManager()直接实例化,因为构造函数是私有的。你需要通过静态方法或静态属性获取唯一实例:
// 方式1:调用现有getManager方法 var manager = ZoneManager.getManager(); // 方式2(优化后):直接访问静态实例 var manager = ZoneManager.Instance; // 功能调用示例 bool hasAccess = manager.requestAccess("ZoneA", "RobotArm1"); if (hasAccess) { // 执行运动逻辑 manager.returnContent("ZoneA", "RobotArm1"); }
3. 通过WCF调用时如何确保所有请求指向同一实例?
WCF默认采用PerCall实例模式(每个请求创建新实例),会破坏单例。要让所有WCF调用共享同一个ZoneManager实例,需按以下步骤配置:
步骤1:实现WCF服务契约
创建服务契约接口,暴露ZoneManager的核心功能:
[ServiceContract] public interface IZoneManagerService { [OperationContract] bool RequestAccess(string zone, string resource); [OperationContract] void ReturnContent(string zone, string resource); } public class ZoneManagerService : IZoneManagerService { // 复用已有的单例实例 private readonly ZoneManager _manager = ZoneManager.getManager(); public bool RequestAccess(string zone, string resource) { return _manager.requestAccess(zone, resource); } public void ReturnContent(string zone, string resource) { _manager.returnContent(zone, resource); } }
步骤2:配置WCF单例实例模式
在WCF配置文件或代码中,将服务实例模式设置为Single,确保WCF宿主仅创建一个ZoneManagerService实例,所有客户端请求复用该实例:
- 配置文件方式:
<system.serviceModel> <services> <service name="Mechanical_Interactions.ZoneManagerService"> <endpoint address="" binding="basicHttpBinding" contract="Mechanical_Interactions.IZoneManagerService"/> <host> <baseAddresses> <add baseAddress="http://localhost:8080/ZoneManagerService"/> </baseAddresses> </host> </service> </services> <behaviors> <serviceBehaviors> <behavior> <serviceMetadata httpGetEnabled="true"/> <!-- 设置实例模式为Single --> <serviceBehaviorAttribute InstanceContextMode="Single"/> <serviceDebug includeExceptionDetailInFaults="false"/> </behavior> </serviceBehaviors> </behaviors> </system.serviceModel>
- 代码配置方式:
var host = new ServiceHost(typeof(ZoneManagerService), new Uri("http://localhost:8080/ZoneManagerService")); var serviceBehavior = host.Description.Behaviors.Find<ServiceBehaviorAttribute>() ?? new ServiceBehaviorAttribute(); serviceBehavior.InstanceContextMode = InstanceContextMode.Single; host.Description.Behaviors.Add(serviceBehavior); host.Open();
配置完成后,所有客户端的WCF请求都会指向同一个ZoneManagerService实例,自然共享唯一的ZoneManager单例,保证区域状态的全局一致性。
内容的提问来源于stack exchange,提问作者Medic3000
相关产品推荐
相关产品推荐

