繁体   English   中英

如何与派生类正确共享基类静态属性

[英]How to properly share base class static property with derived classes

我有一个基类,其中包含执行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。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM