我有一个基类,其中包含执行http请求的基本逻辑。但是我需要某种开关,因为根据用户设置的配置,url 的域会发生变化。
在此基础上,我创建了一个静态属性,该属性包含一个枚举,负责为我提供所需的基值。最重要的是,基类将通过 nuget 包分发,因此它对用户来说在某种程度上是密封的,用户只需要实现其必填字段,就可以使用在其父级上定义的任何逻辑。
所以基本上到目前为止我想出了这个解决方案。
public abstract class Base{
protected static Environment Environment { get; set; }
public static Init(Environment NewEnvironment){
Environment = NewEnvironment;
}
public void UseEnvironment(){
//use the selected environment on the method
}
}
public A : Base{
public void UseAEnvironment(){
UseEnvironment(); //using the environment defined with A.init() call
}
}
public B : Base{
public void UseBEnvironment(){
UseEnvironment(); //using the environment defined with B.init() call
}
我知道内存中只有一个静态属性的副本,因此当您将其设置为 A 类的值时,B 最终将使用相同的值。
我需要能够做
A.Init(Environment.Debug);
B.Init(Environment.Release);
因此,当我运行程序时,类 A 中定义的所有方法都将使用 Debug 值运行,而类 B 将具有 Release 值。
我的解决方案没有做我需要的,有没有办法让它工作,或者是否有更好的架构决策来避免这种情况并实现类似的结果?
如果您有:
public abstract class Base<T> where T : Base<T>
{
protected static Environment Environment { get; private set; }
public static void Init(Environment newEnvironment)
{
Environment = newEnvironment;
}
}
然后:
public class A : Base<A>
{
...
}
public class B : Base<B>
{
...
}
然后你可以做:
Base<A>.Init(Environment.Debug);
Base<B>.Init(Environment.Release);
它之所以有效,是因为在Base<T>
中,每次替换T
的东西都有自己的静态成员。也就是说,每个构造的泛型类型("封闭"泛型类型(都有单独的静态字段。
您也可以将其写为:
A.Init(Environment.Debug);
B.Init(Environment.Debug);
但我认为这有点令人困惑,即使它是一个更紧凑的语法。
这似乎是一个有点奇怪的设计。也许像编译器指令(#if DEBUG(或通过App.config或类似的东西会更适合?
无论如何,如果不是..类似以下内容应该可以工作
public abstract class Base<T> where T : Base<T>
{
private static readonly IDictionary<Type, Environment> _Environments = new Dictionary<Type, Environment>();
public static void Init(Environment NewEnvironment)
{
_Environments[typeof(T)] = NewEnvironment;
}
protected Environment GetEnvironment()
{
if (!_Environments.ContainsKey(typeof(T)))
return default(Environment);
return _Environments[typeof(T)];
}
}
public class A : Base<A> {
// ...
}
public class B : Base<B> {
// ...
}
我不喜欢以下建议的代码,但它代表了最小的代码剧变量,以提供我认为您要做的事情。 请注意抽象基类中删除的静态声明。
public abstract class Base {
protected Environment Environment { get; set; }
public Init(Environment NewEnvironment) {
Environment = NewEnvironment;
}
}
public A : Base{
public void UseEnvironment() {
}
}
public B : Base{
public void UseEnvironment() {
}
}
然后初始化。
static A DebugHttpAccess;
static B RealeaseHttpAccess;
DebugHttpAccess = new A();
DebugHttpAccess.Init(Environment.Debug);
RealeaseHttpAccess= new B();
RealeaseHttpAccess.Init(Environment.Release);
最后按照其他更高级别的逻辑使用:
if ( needDebugHttpTracing )
DebugHttpAccess.UseEnvironment();
else
ReleaseHttpAccess.UseEnvironment();
我怀疑满足您要求的正确解决方案涉及控制反转和一个可以将 Http 访问的生命周期作为单例类进行管理的容器。容器将注入由其他进程范围的配置设置定义的相应 Http 访问实例。
有关 IOC 容器的示例,请参阅 autofac.org。