I am building a logging class and it formats the message differently based on the method name. I want to be able to use it in a similar way to how Console.WriteLine() works. Overloading works just fine, but I want to do this with a set of different methods, the name being the determining factor on the formatting option.
I am looking to see if there is a 'smarter' way to do this other then writing every overloaded method of every version of the same method over and over. That just feels so, bug prone.
Some examples of how I want to use it:
Logger Log = new Logger(); Log.Prod ("Main Log Window"); Log.Warn ("This is a Warning Message"); Log.Error ("This is an Error Message"); Log.Network ("This is a Network Message"); Log.Verbose ("This is for Verbose Message Reporting"); Log.Processing ("Analaysis Related Message"); For what I mean how to use Console.WriteLine, I mean in ways like this:
String Name = "Sam"; String Day = "Monday"; int hour = 11; int minute = 30; Console.WriteLine ("Hello World"); Console.WriteLine ("Hello {0}", Name); Console.WriteLine ("{0}, the time is {1}:{2}", Name, hour, minute); So, what I would end up with is more like this:
Logger Log = new Logger(); Log.Prod ("Staring Application"); Log.Warn ("Data {0} looks Corrupt",data); Log.Error ("Error: {0}", message); Log.Network ("User {0} logged in from {1}", user, network); Log.Verbose ("This is for Verbose Message Reporting"); Log.Processing ("Analaysis Related Message"); Now, I know I can code each and every overloaded method for each of those versions of the same routine, (remember, each will format the message a little differently), and I could put some kind of 'code' on it, like:
Log.Write (Log.Error ,"Error: {0}", message); ... and Log.Error be some kind of enum or what ever, but this is nasty.
What I'd like to do is bake this all down to a case statement that would handle the formatting and then feed that into the output. Most of the code I need to write is all this overloading relaying that's 99% repeat of the same exact thing. There's got to be a smarter way.
I've seen a few things in other languages that might do this, but I am looking for a C# (.Net Framework 4.8) way of doing this if possible. What would be the 'cleanest' and 'smarter' way of doing it besides writing it all out?
I've looked at overloading, overriding, templates, interfaces, etc. But so far, it all looks as if it would wind up being the same outcome or worse.
-- edit
I have an old version that did something like this:
... public static void Log (Type LogType, object Msg, object [] args ) { // Using Type specifier and format options. String NewMsg = String.Format (Msg.ToString(), args); Logger.Log ((int) LogType, NewMsg); } public static void Log (Type LogType, object Msg, object arg1, object arg2 ) { // Using Type specifier and format options. String NewMsg = String.Format (Msg.ToString(), arg1, arg2); Logger.Log ((int) LogType, NewMsg); } public static void Log (Type LogType, object Msg, object arg1, object arg2, object arg3 ) { // Using Type specifier and format options. String NewMsg = String.Format (Msg.ToString(), arg1, arg2, arg3); Logger.Log ((int) LogType, NewMsg); } ... What I was trying to see is if I could get rid of that 'Type' parameter and use the name of the function to forward it. Maybe that is some kind of template or overloading. I think I might have built it doing some copy/paste from Console.WriteLine, (been a while) or at least used it as a starting place.
I know the long way works, I was just hoping for a 'smarter' version, but so far, it doesn't seem there is one.
This likely has errors, just tossed it together as an example of the long way...
... public static void Warn(object Msg, object[] args) { // Using Type specifier and format options. String NewMsg = String.Format (Msg.ToString(), args); Logger.Log(1, NewMsg); } public static void Warn(object Msg, object arg1, object arg2) { // Using Type specifier and format options. String NewMsg = String.Format (Msg.ToString(), arg1, arg2); Logger.Log(1, NewMsg); } public static void Warn(object Msg, object arg1, object arg2, object arg3) { // Using Type specifier and format options. String NewMsg = String.Format (Msg.ToString(), arg1, arg2, arg3); Logger.Log(1, NewMsg); } ... public static void Error(object Msg, object[] args) { // Using Type specifier and format options. String NewMsg = String.Format (Msg.ToString(), args); Logger.Log(2, NewMsg); } public static void Error(object Msg, object arg1, object arg2) { // Using Type specifier and format options. String NewMsg = String.Format (Msg.ToString(), arg1, arg2); Logger.Log(2, NewMsg); } public static void Error(object Msg, object arg1, object arg2, object arg3) { // Using Type specifier and format options. String NewMsg = String.Format (Msg.ToString(), arg1, arg2, arg3); Logger.Log(2, NewMsg); } ... So, that can get pretty long if I do what I want, and I can, I was just wondering if there was a better way.
This was when I was learning about overloading, so, yea.
--- Edit: Working:
I had to make a few tricks to get it all to gyrate, but incase anyone ever needs it, here is what I came up with:
working sample code snippets:
Logger Log = new Logger(); String name = "George"; long records = 200000; String network = "someplace.com"; int hour = 10; int minute = 30; Log.Prod (); Log.Warn ("Project Starting"); Log.Warn (network); Log.Prod ("Hello {0}!", name); Log.Prod ($"Hello {name}!"); Log.Processing("{0} Processed", records); Log.Processing($"{records} Processed"); Log.Network($"{name} logged in from {network} at {hour}:{minute}"); Log.Network("{0} logged in from {1} at {2}:{3}", name, network, hour, minute); Now, I don't have my format stuff in here yet, (not relevant but the value is there to be used, It's going to a console log window so they will be colored and various stamps will wrap them, but that's the easy part for later.)
public class Logger { public Logger () { if (LogSubsystem.Init == true) { return; } else { // Do some setup stuff here. } } public void Prod(params object[] args) { LogMessage(1, args); } public void StatusBar(params object[] args) { LogMessage(2, args); } public void TitleBar(params object[] args) { LogMessage(3, args); } public void Verbose(params object[] args) { LogMessage(4, args); } public void Status(params object[] args) { LogMessage(5, args); } public void Network(params object[] args) { LogMessage(6, args); } public void Account(params object[] args) { LogMessage(7, args); } public void Error(params object[] args) { LogMessage(8, args); } public void Warn(params object[] args) { LogMessage(9, args); } public void Processing(params object[] args) { LogMessage(10, args); } public void DebugLow(params object[] args) { LogMessage(11, args); } public void DebugMid(params object[] args) { LogMessage(12, args); } public void DebugHigh(params object[] args) { LogMessage (13, args); } private void LogMessage(int mode, object [] args) { var property = typeof(ICollection).GetProperty("Count"); int count = (int)property.GetValue(args, null); ... many things missing.... if (count == 0) { Console.WriteLine (""); } if (count == 1) { Console.WriteLine ("{0}", args[0]); } if (count > 1) { ArraySegment<object> ASargs = new ArraySegment<object>(args, 1, (count-1)); object [] SubArgs = ArraySegmentToArray(ASargs); Console.WriteLine (args[0].ToString(), SubArgs); } } private object [] ArraySegmentToArray (ArraySegment<object> segment) { var result = new object[segment.Count]; for (int i = 0; i < segment.Count; i++) { result[i] = segment.Array[i + segment.Offset]; } return result; } } // Logger class And the output works:
Project Starting someplace.com Hello George! Hello George! 200000 Processed 200000 Processed George logged in from someplace.com at 10:30 George logged in from someplace.com at 10:30
Some of these will eventually set the status bar, title bar, etc, is why those are there. (you'd set a reference to those objects in stuff that doesn't exist here yet, my old one does it, so, moving that over) The tricky part is the ArraySegment Stuff, maybe an easier way to do it, but it's short enough and works that I don't care. It surprised to find that ArraySegment doesn't have a ToArray(), yea, didn't see that one coming. Anyway, Thanks!!!
https://stackoverflow.com/questions/66535847/in-c-sharp-is-there-a-smarter-way-to-overload-a-set-of-methods-with-different-na March 09, 2021 at 03:19AM
没有评论:
发表评论