2017-08-05 19 views
0

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 
    } 

は、私はあなたがクラスの値に設定したときにこのように、Bが同じ値を使用して終了します、メモリ内の静的プロパティのコピーが1つだけであることを知っています。

私はプログラムを実行すると、クラスBがリリース値を持つことになりますしながら、だから、クラスAで定義されたすべてのメソッドは、デバッグ値で実行されます

A.Init(Environment.Debug); 
B.Init(Environment.Release); 

を行うことができるようにする必要があります。

私のソリューションは、私が必要としていることをしません、それを動作させる方法はありますか、この状況を回避して同様の結果を達成するために、

+2

「静的」の場合はインスタンスに属しません。そして、あなたの「環境」は本当にインスタンスに属しているようです。それはなぜ静的なのですか? – 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<T>Tのための何かの各置換は持っているので

Base<A>.Init(Environment.Debug); 
Base<B>.Init(Environment.Release); 

それは動作しますそれ自身の静的メンバー。つまり、それぞれジェネリックタイプ(「クローズド」ジェネリックタイプ)は、別々の静的フィールドを持っています。

またとしてそれを書くことができます:

A.Init(Environment.Debug); 
B.Init(Environment.Debug); 

が、私はそれがよりコンパクトな構文であったとしても、その少し混乱検討します。

+0

私の投票を取得、それは私の答えよりも洗練されたソリューションです。私はまだ適切な長期的な解決策がIOCコンテナを利用すると思いますが、提供される回答は問題のサンプルコードの周りに形作られていることを感謝します。 – camelCase

+0

OKですが、彼のコードを修正するのではなく、フィールドを静的にすることを捨ててしまったはずです。 'public abstract class Base { のようなものです。保護されたセット。 }} 'メンバは静的ではありません_より良いことがあります。それはもっと普通です、少なくとも。しかし、私はこれが何のために使われるのか正確にはわかりません。 –

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

なぜ、 'Dictionary <,>'は使用されていないので、複数のキー、つまり '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を参照してください。

関連する問題