簡體   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