Avoiding “Access to a static member of a type via

2019-05-20 15:34发布

问题:

I believe this is purely a Resharper warning, but the reasoning behind it (explained here) makes good sense. What Greg Beech is saying is that you can call a base-class static method from a sibling class... in his example he uses:

var request = (FtpWebRequest)HttpWebRequest.Create(...)

... which is misleading.

So is there a design that would allow me to avoid this warning in the following classes?

public abstract class BaseLog {

    //  I omitted several other properties for clarity
    protected static string category;
    protected static TraceEventType severity;

    static BaseLog() {
        category = "General";
        severity = TraceEventType.Information;
    }

    public static void Write(string message) {
        Write(message, category, severity);
    }

    //  Writes to a log file... it's the same code for 
    //  every derived class.  Only the category and severity will change
    protected static void Write(string message, string messageCategory, TraceEventType messageSeverity) {

        LogEntry logEntry = new LogEntry(message, messageCategory, messageSeverity);

        //  This is Microsoft's static class for logging... I'm wrapping it to 
        //  simplify how it's called, but the basic principle is the same:
        //  A static class to log messages
        Logger.Write(logEntry);

    }

}


public class ErrorLog : BaseLog {

    static ErrorLog() {
        category = "Errors";
        severity = TraceEventType.Error;
    }

    //  I can add more functionality to the derived classes, but
    //  the basic logging functionality in the base doesn't change
    public static void Write(Exception exc) {
        Write(exc.Message);
    }

}


//  Code that could call this...
catch (Exception exc) {
    //  This line gives me the warning
    ErrorLog.Write("You did something bad");
    ErrorLog.Write(exc);
}

One ErrorLog serves the application, and its settings never change (there's also a TraceLog and a ThreadLog). I don't want to duplicate the logging code, because it's exactly the same for every derived class... keeping it in BaseLog works perfectly. So how do I design this that I'm not violating this design principle?

The classes are static because I don't want to instantiate a new ErrorLog object every time I want to log something, and I don't want 50 of them floating around in the form of a member-level variable in every class I write. The logging is using Microsoft's Enterprise Library, if that makes a difference.

TIA!
James

回答1:

It seems like you want to keep the door open for extension but not for modification aka the Open Closed principle. And its a worthy goal.

My advice would be to lose the static cling - turn the function-holder classes into objects. This allows you to override (and not confuse other readers) as required - polymorphism only works with instances.

The next concern would be the need to have a global object vs passing a logger instance around. Create another type that provides access to a single instance of a logger object. (the old singleton)

e.g. ErrorLogProvider.Instance.Write(something)

PS: Freebie - easier to test these objects too.