Статический класс наследуется от базового члена изменения - PullRequest
2 голосов
/ 10 июля 2019

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

Этот подход не работает, потому что статический класс не может быть производным от чего-либо еще, кроме объекта.Есть ли другой способ изменить свойство?

Ответы [ 4 ]

1 голос
/ 10 июля 2019

Использование статического класса означает использование синглтона. Синглтоны побеждают цель отслеживания эффективных зависимостей ваших классов.

В любом случае, вы можете решить проблему путем рефакторинга кода и использования фабрики:

В этом случае просто отбросьте ключевое слово 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 (который может быть унаследован) в качестве аргумента методов / конструкторов, когда это необходимо.

1 голос
/ 10 июля 2019

Я не вижу, что вам нужно более одного статического класса. Вместо этого разделите логику на методы в одном статическом классе.

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");
1 голос
/ 10 июля 2019

У вас здесь много статических классов, и я не совсем уверен, что они необходимы. Мой пример не использует статические классы, кроме вашей 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";
    }
}

Чтобы получить вывод, вам просто нужно создать новые экземпляры ModuleA и ModuleB.

var moduleA = new ModuleA();
var moduleB = new ModuleB();
moduleA.Write("Hi");
moduleB.Write("Hi");
0 голосов
/ 10 июля 2019

Если вы не можете изменить класс 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";
}
...