Shawn
Shawn

Reputation: 177

Static class derive from base change member

In C# a static class can not derive from any other class besides object. Currently I have this base class:

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

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

Now, depending on which class I'm using, I want to change 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
    }
}

Supposed to be called like this

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

This approach does not work because a static class cannot derive from anything else than object. Is there any other way to change the property?

Upvotes: 2

Views: 130

Answers (4)

Vladislav Maximov
Vladislav Maximov

Reputation: 11

If you can't change the BaseModule class, you can use it with other state and recover state after using:

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";
}

But you must ensure thread safety.

If you can change the BaseModule class:

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";
}

Upvotes: 0

juharr
juharr

Reputation: 32276

I don't see that you need more than one static class. Instead separate the logic into methods in one static class.

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);
    }
}

Then instead of

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

you'd do

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

Upvotes: 1

Yennefer
Yennefer

Reputation: 6234

Using a static class means using a singleton. Singletons defeat the purpose of tracking the effective dependencies of your classes.

Anyway, you can approach the problem by refactoring your code and using a factory:

In this case, just drop the static keyword and let the class be inheritable (you have to add the appropriate virtual keywords to allow proper inheritance):

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

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

Then, add an additional class which holds the reference (I gave useless names, focus on the purpose):

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;
    }
}

This way wou can achieve what you ask.

As you can see, this code has several issues, among them it's important to note that this code has global side effects and is not thread safe.

A better approach is to have drop the singleton entirely, and pass the BaseModule class (that can be inherited) as an argument of methods/constructors when needed.

Upvotes: 1

Airn5475
Airn5475

Reputation: 2492

You have a lot of static classes going on here and I'm not entirely sure they're necessary. My example does not use static classes other than for the OtherStaticClass reference you have. I understand this may not be quite what you're looking for; many ways to skin this cat.

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";
    }
}

To get your output then, you just need to create new instances of ModuleA and ModuleB.

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

Upvotes: 1

Related Questions