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
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)
PS: Freebie - easier to test these objects too.