如何在C#不同解决方案间迁移依赖全局变量的共享类?
我有两个解决方案A和B,每个解决方案包含两个项目:
- 解决方案A:ProjectX,引用Common项目
- 解决方案B:ProjectY,引用Common项目
Common项目包含一些独立的通用类。ProjectX和ProjectY各自拥有运行时专属的全局变量,二者均定义了如下Globals类:
public class Globals { public static dynamic vaProxy; ... }
在解决方案A/B运行时,会先初始化Globals.vaProxy及其他全局变量,供大量类调用,例如:
Globals.vaProxy.WriteToLog("somthing...")
或访问:
Globals.someVAriableName
我希望将ProjectX和ProjectY中的相似类迁移至Common项目以避免重复代码,但目前Common项目仅包含不依赖Globals.vaProxy或Globals.someVar的类。请问能否将依赖全局变量的类迁移至无Globals定义的Common项目?
完全可以迁移,核心是让Common项目不直接依赖ProjectX/Y的Globals类,以下是几种实用的实现方式:
1. 依赖注入(推荐)
先在Common项目中定义抽象接口,把Globals的能力抽离出来:
// Common项目内定义 public interface IVaProxy { void WriteToLog(string message); // 按需添加其他vaProxy的方法 } public interface IGlobalContext { IVaProxy VaProxy { get; } object SomeVariableName { get; } // 其他需要的全局变量属性 }
然后Common项目中的通用类通过构造函数注入IGlobalContext来使用全局能力:
// Common项目中的通用业务类 public class CommonBusinessService { private readonly IGlobalContext _globalContext; public CommonBusinessService(IGlobalContext globalContext) { _globalContext = globalContext; } public void ExecuteBusinessLogic() { _globalContext.VaProxy.WriteToLog("执行通用逻辑"); var variableValue = _globalContext.SomeVariableName; // 具体业务代码 } }
最后在ProjectX和ProjectY中,分别实现IGlobalContext接口,将各自的Globals类包装进去:
// ProjectX中的实现 public class ProjectXGlobalContext : IGlobalContext { public IVaProxy VaProxy => Globals.vaProxy; public object SomeVariableName => Globals.someVAriableName; } // ProjectY中的实现类似,替换为ProjectY的Globals
运行时通过依赖注入容器注入对应的IGlobalContext实现即可。这种方式解耦彻底,扩展性强,符合SOLID原则。
2. 静态委托绑定
如果项目规模较小,不想引入DI框架,可以用静态委托的方式实现:
// Common项目内定义 public static class CommonGlobalDelegates { public static Action<string> WriteToLog { get; set; } public static Func<object> GetSomeVariable { get; set; } }
在ProjectX的初始化代码中(比如启动入口),绑定委托到自己的Globals:
// ProjectX启动时执行 CommonGlobalDelegates.WriteToLog = msg => Globals.vaProxy.WriteToLog(msg); CommonGlobalDelegates.GetSomeVariable = () => Globals.someVAriableName;
Common项目中的类直接调用这些委托:
public class CommonBusinessService { public void ExecuteBusinessLogic() { CommonGlobalDelegates.WriteToLog("执行通用逻辑"); var variableValue = CommonGlobalDelegates.GetSomeVariable(); } }
这种方式实现简单,但耦合度比DI高,适合小型场景。
3. 反射(兜底方案,不推荐)
如果以上两种方式都无法落地,可以用反射动态获取Globals的成员,但这种方式维护成本高,耦合严重:
// Common项目中的类 public class CommonBusinessService { public void ExecuteBusinessLogic() { // 根据运行环境动态获取Globals类型 var globalsType = AppDomain.CurrentDomain.GetAssemblies() .SelectMany(a => a.GetTypes()) .FirstOrDefault(t => t.Name == "Globals"); if (globalsType == null) throw new InvalidOperationException("未找到Globals类"); // 获取vaProxy并调用方法 var vaProxy = globalsType.GetProperty("vaProxy").GetValue(null); vaProxy.GetType().GetMethod("WriteToLog")?.Invoke(vaProxy, new object[]{"执行通用逻辑"}); // 获取全局变量 var variableValue = globalsType.GetProperty("someVAriableName").GetValue(null); } }
这种方式不推荐,除非是遗留系统改造且无法修改现有Globals结构的情况。
内容的提问来源于stack exchange,提问作者dandan21

