【问题标题】:Static class derive from base change member静态类派生自基本更改成员
【发布时间】:2019-07-10 11:51:15
【问题描述】:

在 C# 中,静态类不能从对象以外的任何其他类派生。 目前我有这个基类:

public static class BaseModule
{
    public static string UsedSource {get; set;}

    public static Write(string text)
    {
        OtherStaticClass.Log(UsedSource, text);
    }
}

现在,根据我使用的类,我想更改UsedSource

// this does not work
internal static class ModuleA : BaseModule
{
    static ModuleA(){
        UsedSource = "A" // just an example
    }
}

// this does not work
internal static class ModuleB : BaseModule
{
    static ModuleB(){
        UsedSource = "B" // just an example
    }
}

应该这样称呼

ModuleA.Write("Hi");
ModuleB.Write("Hi");

这种方法不起作用,因为静态类不能从对象以外的任何东西派生。 有没有其他方法可以改变属性?

【问题讨论】:

  • 如果你想要继承特性,为什么还要使用静态类?
  • 如果你同时使用这两个模块会怎样?
  • @TimSchmelter 该类是无状态的,只是“按原样”提供功能。唯一的上下文是UsedSource。由于调用频繁,我也不想每次都将该参数作为参数传递。
  • @LasseVågsætherKarlsen 两个模块都在不同的项目中,它们不会在同一个程序集中同时被引用。但是,这两个模块都引用了实现基类的核心。
  • 这是单例模式的绝佳选择。而是调查一下。

标签: c# inheritance static overriding


【解决方案1】:

这里有很多静态类,我不完全确定它们是否必要。除了您拥有的 OtherStaticClass 参考之外,我的示例不使用静态类。我知道这可能不是您想要的;给这只猫剥皮的方法很多。

public abstract class BaseModule
{
    public string UsedSource { get; set; }

    public void Write(string text)
    {
        OtherStaticClass.Log(UsedSource, text);
    }   
}

public class ModuleA : BaseModule
{
    public ModuleA()
    {
        UsedSource = "A";
    }   
}

public class ModuleB : BaseModule
{
    public ModuleB()
    {
        UsedSource = "B";
    }
}

然后,要获得输出,您只需创建 ModuleAModuleB 的新实例。

var moduleA = new ModuleA();
var moduleB = new ModuleB();
moduleA.Write("Hi");
moduleB.Write("Hi");

【讨论】:

  • 然后您可以在入口点创建实例并将其传递给需要它的类的承包商。这种方法不应该解决问题的根源。
【解决方案2】:

使用静态类意味着使用单例。单例破坏了跟踪类的有效依赖关系的目的。

无论如何,您可以通过重构代码和使用工厂来解决问题:

在这种情况下,只需删除 static 关键字并让类可继承(您必须添加适当的 virtual 关键字以允许正确继承):

public class BaseModule
{
    public string UsedSource {get; set;}

    public Write(string text)
    {
        OtherStaticClass.Log(UsedSource, text);
    }
}

然后,添加一个包含引用的附加类(我给出了无用的名称,重点关注目的):

public static class MySingleton
{
    public static BaseModule _Module;

    public static BaseModule Module
    {
        get
        {
            return _Module;
        }
    }

    public static void ChangeImplementation (BaseModule module)
    {
        // do your checks here

        _Module = module;
    }
}

这样你就可以实现你的要求。

如您所见,这段代码有几个问题,其中重要的是要注意这段代码有全局副作用并且不是线程安全的

更好的方法是完全放弃单例,并在需要时将 BaseModule 类(可以继承)作为方法/构造函数的参数传递。

【讨论】:

    【解决方案3】:

    我认为您不需要多个静态类。而是将逻辑分成一个静态类中的方法。

    public static class Module
    {   
        private const string SourceA = "A";
        private const string SourceB = "B";
    
        public static WriteA(string text)
        {
            Write(SourceA, text);
        } 
    
        public static WriteB(string text)
        {
            Write(SourceB, text);
        } 
    
        private static Write(string source, string text)
        {
            OtherStaticClass.Log(source, text);
        }
    }
    

    然后代替

    ModuleA.Write("Hi");
    ModuleB.Write("Hi");
    

    你会的

    Module.WriteA("Hi");
    Module.WriteB("Hi");
    

    【讨论】:

      【解决方案4】:

      如果你不能改变BaseModule类,你可以将它与其他状态一起使用,使用后恢复状态:

      public static class BaseModule
      {
          public static string UsedSource {get; set;}
      
          public static Write(string text)
          {
              OtherStaticClass.Log(UsedSource, text);
          }
      }
      
      internal class Writer : IDisposable
      {
          string _lastSource;
      
          public Writer(string source)
          {
              _lastSource = BaseModule.UsedSource;
              BaseModule.UsedSource = source;
          }
      
          public void Dispose()
          {
              BaseModule.UsedSource = _lastSource;
          }
      }
      
      internal abstract class Module
      {
          public abstract Source { get; };
      
          public void Write(string text)
          {
              using (var writer = new Writer(Source))
              {
                  BaseModule.Write(text);
              }
          }   
      }   
      
      internal class ModuleA : Module
      {   
          public override Source => "A";
      }
      
      internal class ModuleB : Module
      {   
          public override Source => "B";
      }
      

      但你必须确保线程安全。

      如果您可以更改 BaseModule 类:

      public static class BaseModule
      {    
          public static Write(string text, string source)
          {
              OtherStaticClass.Log(source, text);
          }
      }
      
      internal abstract class Module
      {
          public abstract Source { get; };
      
          public void Write(string text)
          {       
              BaseModule.Write(text, Source);     
          }   
      }   
      
      internal class ModuleA : Module
      {   
          public override Source => "A";
      }
      
      internal class ModuleB : Module
      {   
          public override Source => "B";
      }
      

      【讨论】:

        猜你喜欢
        • 2018-11-30
        • 2023-03-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-12-05
        • 2011-07-17
        • 2016-10-15
        • 1970-01-01
        相关资源
        最近更新 更多