C# 如何与派生类正确共享基类静态属性
我有一个基类,它包含执行http请求的基本逻辑。但是,我需要某种类型的切换,因为依赖于用户设置的配置,url的域将发生变化 基于此,我创建了一个静态属性,该属性包含一个枚举,负责为我提供所需的基值。最重要的是,基类将通过nuget包分发,因此它对用户来说有些密封,用户只需实现其必需的字段,就可以使用在其父类上定义的任何逻辑 到目前为止,我基本上提出了这个解决方案C# 如何与派生类正确共享基类静态属性,c#,class,inheritance,static,C#,Class,Inheritance,Static,我有一个基类,它包含执行http请求的基本逻辑。但是,我需要某种类型的切换,因为依赖于用户设置的配置,url的域将发生变化 基于此,我创建了一个静态属性,该属性包含一个枚举,负责为我提供所需的基值。最重要的是,基类将通过nuget包分发,因此它对用户来说有些密封,用户只需实现其必需的字段,就可以使用在其父类上定义的任何逻辑 到目前为止,我基本上提出了这个解决方案 public abstract class Base{ protected static Environment Enviro
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值
我的解决方案不能满足我的需要,是否有办法让它工作,或者是否有更好的架构决策来避免这种情况并实现类似的结果?这似乎是一个有点奇怪的设计。也许像编译器指令(#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> {
// ...
}
公共抽象类基类,其中T:Base
{
私有静态只读IDictionary _Environments=new Dictionary();
公共静态void Init(环境NewEnvironment)
{
_环境[类型(T)]=新环境;
}
受保护的环境GetEnvironment()
{
if(!_Environments.ContainsKey(typeof(T)))
返回默认值(环境);
返回_环境[类型(T)];
}
}
公共A类:基本类{
// ...
}
B类公共服务:基本服务{
// ...
}
这看起来有点奇怪。也许像编译器指令(#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> {
// ...
}
公共抽象类基类,其中T:Base
{
私有静态只读IDictionary _Environments=new Dictionary();
公共静态void Init(环境NewEnvironment)
{
_环境[类型(T)]=新环境;
}
受保护的环境GetEnvironment()
{
if(!_Environments.ContainsKey(typeof(T)))
返回默认值(环境);
返回_环境[类型(T)];
}
}
公共A类:基本类{
// ...
}
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 我不喜欢下面建议的代码,但它代表了最小数量的代码变动,以提供我认为您正在尝试的内容。请注意,在抽象基类中删除了静态声明
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 如果您有:
public abstract class Base<T> where T : Base<T>
{
protected static Environment Environment { get; private set; }
public static void Init(Environment newEnvironment)
{
Environment = newEnvironment;
}
}
<> p>但我认为这有点让人困惑,即使它是一个更紧凑的语法。 如果你有:
public abstract class Base<T> where T : Base<T>
{
protected static Environment Environment { get; private set; }
public static void Init(Environment newEnvironment)
{
Environment = newEnvironment;
}
}
<> p>但我认为这会稍微混淆,即使它是一个更紧凑的语法。如果是<代码> static ,它不属于一个实例。而且您的
环境
似乎确实应该属于一个实例。为什么它是静态的?使用静态属性不是应该避免的吗?可能您正在尝试解决一个?如果它是静态的
,则它不属于实例。而且您的环境
似乎确实应该属于一个实例。为什么它是静态的?使用静态属性不是应该避免的吗?也许你正在试图解决一个问题?为什么,字典没有用,它不会有多个键,即typeof(T)
。不同构造的泛型类型之间不共享静态
字段\u环境
。(见我的答案。)为什么,字典
没有用处,它不会有多个键,即typeof(T)
。不同构造的泛型类型之间不共享静态
字段\u环境
。(见我的答案)得到我的投票,这是一个比我的答案更复杂的解决方案。我仍然认为一个合适的长期解决方案将使用IOC容器,但是我很感激提供的答案是围绕问题中的示例代码形成的。好吧,但也许我应该放弃询问者希望字段静态
的愿望,而不是修复他的代码。类似于public abstract class Base{public abstract Environment{get;protected set;}}
这样的非静态成员可能更好。至少,这更为常见。但我不知道这到底是用来做什么的。如果我投了票,这是一个比我的答案更复杂的解决方案。我仍然认为,一个合适的长期解决方案将利用国际奥委会的容器,但我很欣赏答案是公关