2017-08-05 30 views
0

我有一个基类,它包含执行一个http请求的基本逻辑。不过,由于依赖于用户设置的配置,我需要进行某种切换,因此网址的域名将会更改。如何正确地与派生类共享基类静态属性

基于此,我创建了一个静态属性,其中包含一个枚举,负责给我所需的基值。最重要的是,基类将通过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类中定义的所有方法都与调试运行值,而B类将有释放值。

我的解决方案没有做到我需要的东西,有没有办法让它工作,或者是否有更好的架构决策来避免这种情况并实现类似的结果?

+2

如果它是'static',它不属于一个实例。看起来你的'环境'应该属于一个实例。为什么它是静态的呢? – Andrew

+0

是不是使用静态属性的东西,应该避免?也许你正在试图解决[XY问题](http://xyproblem.info/)? –

回答

2

如果您有:

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); 

但我认为稍显混乱,即使它是一个更简洁的语法。

+0

获得我的投票,这是比我的答案更复杂的解决方案。我仍然认为一个适当的长期解决方案将利用IOC容器,但我很欣赏提供的答案是围绕问题中的示例代码形成的。 – camelCase

+0

好的,但也许我应该放弃提问者希望有'静态'字段而不是固定他的代码。类似于'公共抽象类基础{0}公共抽象环境环境{获取;保护组; }}'成员是非静态的_could_会更好。至少比较平常。但我不确切知道这是用来做什么的。 –

1

这似乎有点奇怪的设计。也许像编译器指令(#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> { 
    // ... 
} 
+0

为什么字典<,>没有用,它永远不会有多个键,即'typeof(T)'。 'static'字段'_Environments'在不同构造的泛型类型之间不被共享。 (查看我的答案) –

0

我不喜欢下面的建议代码,但它代表的代码动荡的最小量,以提供什么,我认为你正在尝试做的。注意在抽象基类中丢弃静态声明。

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。

相关问题