0

I try to built generic logger notification library which could log in different way. It could include file logging, console application logging, debug print logging, database logging etc. I want to have something similar to class that i could define different loggers in list by adding then by Add method and then having that pass that class to consumer class and the fire DoLog() to raise loggers from list. At the moment i stack on DoLog() method. The problem is different loggers classes would have different parameters of their Write() method and i have no idea so far how to call their different parameters methods Write(). Can anyone give a hint/idea how to resolve that or rebuild. Besides any proposition welcome.

This is my current code:

public interface ICanLog { }


        public interface ICanLogConsole : ICanLog
        {
            void Write(string msg);
        }

        public interface ICanLogFile : ICanLog
        {
            void Write(string path, string mag);
        }


        public class ConsoleLogger : ICanLogConsole
        {
            public void Write(string msg)
            {
                throw new NotImplementedException();
            }
        }

        public class FileLogger : ICanLogFile
        {
            public void Write(string path, string mag)
            {
                throw new NotImplementedException();
            }
        }

        public class NotifictionEngine
        {
            public List<ICanLog> Loggers { get; }

            public NotifictionEngine()
            {
                Loggers = new List<ICanLog>();
            }

            public void AddLoggers(ICanLog logger)
            {
                Loggers.Add(logger);
            }

            public void DoLog()
            {
                foreach (var logger in Loggers)
                {
                    //logger should log in his specific way Write()
                    //how to call different parameters Write from loggers?     
               }
            }
        }

EDIT: I was thinking about o use generic interface like ILogger<T> to be able to create my own Loggers but at the moment i do not see where i could use that T as for instance message and path are strings. What could be T here?

dev
  • 39
  • 1
  • 7
  • Better use nlog or log4net. – Uwe Keim Dec 09 '18 at 08:00
  • @UweKeim The key here is to see how could i prepare some code to be able to creates diffrent loggers based on some interface generic solution that i am trying to write. I am stack at the point i've mentioned. – dev Dec 09 '18 at 08:03
  • 2
    While writing logging frameworks is traditional developers pasttime it is not really good topic to ask on SO... Proper practical answer is "use existing logging framework"; if you want to pose it as general design questions it is too broad... It would be more practical to look at an existing logging framework (even basic .Net `Trace.Write` with configurable loggers is good start - at very least you'll see how loggers are configured and what interface they expose). – Alexei Levenkov Dec 09 '18 at 08:04
  • Is this just for personal exploration and learning, or were you hoping to use the result in some production code? – Adam G Dec 09 '18 at 08:04
  • @AlexeiLevenkov i am writing my own solution and i face problem i thought this is the place when there is cocnrete code and the issue i could ask for support here - i am not asking about entire solution. In my case the problem is how to call all loggers resist in Loggers property to do their Write method appropate way. – dev Dec 09 '18 at 08:08
  • 3
    Tip: don't put `string path` in the `Write()` of `ICanLogFile`. Alternatives: put it in the constructor, or use an `Init()` method to initialize it shortly after creation, or use .config-based initialization. – Peter B Dec 09 '18 at 08:11
  • Warning: non-welcome comment. You really should look into existing frameworks. Your interface for logging makes no sense (why would you create token interface for that???) Normally one would start from usage and generalize - other way around is much harder and leads to such strange collection of unrelated interfaces... Why you don't want to have `ILogger:Write(message)` is unclear for me. (Don't forget to flag as unfriendly) – Alexei Levenkov Dec 09 '18 at 08:12
  • @PeterB That could be nice having on mind it's only one thing that differentiate different loggers because at the moment it is so moving as you said path to ctor of FileLogger would solve, but imagine that there is more things diffrentiate should they be always in ctor and common in method itself Write() ?. I was also thinking about that each specific logger could have somespecificconfiguration class like FileLoggerConfiguration, ConsoleLoggerConfiguration that could be passed over ctor. What could be the T here do you see such things? – dev Dec 09 '18 at 08:14
  • Slightly more constructive - check out https://stackoverflow.com/questions/20525277/simple-way-to-perform-error-logging which shows how built in loggers in .Net can be configured and check out MSDN articles about those classes like (ConsoleTraceListener) – Alexei Levenkov Dec 09 '18 at 08:15
  • The main problem is how to call properly Write for each of those items in loop as they all ICanLog but Write parameters are diffrent therefore i cannot put Write into ICanLog. How to solve that? – dev Dec 09 '18 at 08:21
  • Solve it just like Peter B wrote in his comment - pass the `path` parameter into the logger some different way - either by using it's constructor or by using the builder pattern. The write method should not take in the path (or database table, or whatever) - just the message. – Zohar Peled Dec 09 '18 at 08:34
  • @ZoharPeled this seems to be logical then i could put Write(msg) into ICanLog directly and call in loop correctly. Do you see any place here that generic T could be used? – dev Dec 09 '18 at 08:38
  • You can use generics but there's no need to - you can work directly with `ICanLog` (which I would probably call `ILogger` instead). Don't use generics if you don't need to. – Zohar Peled Dec 09 '18 at 08:49
  • @ZoharPeled can you just explain why in this case not generics needed and why ILogger instead ICanLog - i wrote interfaces are more like what i can do – dev Dec 09 '18 at 12:12
  • you don't need generics because you don't care about implementation, you only want to use the `write` method so you only care about the interface. The naming is just a matter of preferences. – Zohar Peled Dec 09 '18 at 12:14
  • @ZoharPeled sorry for offtopic, can you redirect me to read about this "implementation"? Dont get it to be honest – dev Dec 09 '18 at 12:46
  • each log class implements an interface called `ICanLog` in your code. but you don't care about the classes, you just want the `Write` method that's in the interface - implementation, being the concrete classes here, does not matter. – Zohar Peled Dec 09 '18 at 13:12
  • @ZoharPeled hmm what do you mean by "being the concrete classes here, does not matter" ? – dev Dec 09 '18 at 17:17
  • it does not matter to the user where the log gets written. They don't care about it. They just need to use the `Write` method. – Zohar Peled Dec 09 '18 at 19:21

0 Answers0