webForumDet fria alternativet

Bli av med redundant kod...

.NET

4 svar · 652 visningar · startad av CatZ

Medlem sedan jan. 20022 440 inlägg
Frågan#1

Jag har gjort en egen logger, idag skrev jag om den för att den helt enkelt var en jävla röra och det blev för bökigt att göra ändringar i den. Det jag gjort nu är att skapa en basklass för loggern som jag låter mina olika typer av loggers implementera. Sedan ser allihop underklasserna ut likadant.

public class TextLogger : Logger
{
    public TextLogger() { }

    public static void WriteLog() 
    {
        TextLogger logger = new TextLogger();
        logger.Execute();
        logger.Dispose();
    }
    private void Execute() 
    {
        // do stuff
    }
}

Jag har en enum med LogType som jag loopar igenom i de fall lag vill logga till flera källor och jag kan inte komma på något bättre sätt just nu! Några bättre förslag på hur man kan göra?

Medlem sedan maj 20012 812 inlägg
#2

catz skrev:

Jag har en enum med LogType som jag loopar igenom i de fall lag vill logga till flera källor och jag kan inte komma på något bättre sätt just nu! Några bättre förslag på hur man kan göra?

Om du tittar på Log4Net så har de löste den genom att man har typ ett ILogger interface som alla dina olika källor kan implementera, och sedan så beskriver man vilka logkällor som finns i en XML-fil. Då kan du enkelt och utan att behöva ändra i din "logklass" lägga till en massa nya logkällor. Typ MailLogger, SMSLogger osv osv.. Se bara till så de implementerar interfacet och lägg till det i XML-filen.

Interfacet för dina logkällor...

Typ något sånt här:

	public interface IStorageReceiver
	{
		#region -- Properties
                          string Name{get;set;}
		System.Xml.XmlNode Settings{get;set;}
		#endregion

		#region -- Methods
		void StoreMessage(LogMessage message);
		#endregion
	}

Exempel på en logkälla.

	internal class ConsoleReceiver : BaseReceiver
	{
		#region -- Methods
		protected override void StoreMessage(LogMessage message)
		{
			if (!base.CheckForLog(message.LogLevel))
				return;

			Console.WriteLine(message.ToString());
		}
		#endregion

		#region -- Constructor
		public ConsoleReceiver(XmlNode xmlNode) : base(xmlNode) { }
		#endregion
	}

Sedan har du i din "logkod" kod för att läsa in informationen från XML-dokumentet och skapa dessa olika Logkällor. och när du sedan vill logga något så anropar du bara IStorageReceiver.StoreMessage(logMessage).

På det visset så kan du dynamiskt ladda in dina logkällor och skapa instanser av dem med Activator-objektet. Framför allt så kan du skapa nya när du vill utan att behöva ändra i din grundkod...

Glöm dock inte bort att alltid ha en default-logkälla. Typ EventViewer eller c:\_log eller något annat där du kan logga till om nu du inte kan logga till den logkälla som du valt. För om du väljer att logga till en databas, och det inte fungerar (databasen är nere) så måste du ju logga den information + information som du skulle logga, någon annanstans så den inte bara försvinner upp i det blå.

- M

Medlem sedan aug. 20003 575 inlägg
#3

void StoreMessage(LogMessage message); -> void Log(LogMessage message) ftw ).

Medlem sedan sep. 200888 inlägg
#4

CatZ skrev:

Jag har gjort en egen logger, idag skrev jag om den för att den helt enkelt var en jävla röra och det blev för bökigt att göra ändringar i den. Det jag gjort nu är att skapa en basklass för loggern som jag låter mina olika typer av loggers implementera. Sedan ser allihop underklasserna ut likadant.

public class TextLogger : Logger
{
    public TextLogger() { }

    public static void WriteLog() 
    {
        TextLogger logger = new TextLogger();
        logger.Execute();
        logger.Dispose();
    }
    private void Execute() 
    {
        // do stuff
    }
}

Jag har en enum med LogType som jag loopar igenom i de fall lag vill logga till flera källor och jag kan inte komma på något bättre sätt just nu! Några bättre förslag på hur man kan göra?

Tja,

ideén är god men du får lite problem med din kod. Dels så har du static metoder. Försök undivka det. Detta främst för DI/IoC hanteringar men även för mocking...

Har du static kan du inte byta ut dem till ex fakeobjekt eller liknande. Nu är inte fallet så att du kanske måste göra så. men bara att undvika static gör din kod mer löskopplad och förenklar en hel del när förändringar sker.

Sen skulle jag nog gjort så att jag tog emot ett Interface och haft en logger klass sen separata klasser för dina loggers.

ex:

public class Logger
{
    ILogType _logtype; 
    public Logger(ILogtype logtype)
    {
         logType.DontAllowNull("logtype");
         _logtype = logtype;
    }

    public void Write(string message,.....)
    {
          message.DontAllowNullOrEmptyString("message");
          ...
          _logtype.Write(message);
         ...
    }
}

Lite förenklat. Sen kan dina loggers ha olika hanteringar hur de vill logga.
Ex. Via EventLoggen, I en textfil, i en XML, i Db. Och ha olika loggers för det.

Mvh Johan

Medlem sedan jan. 20022 440 inlägg
#5

Det får helt enkelt bli mha observer pattern.

292 ms totalt · 4 externa anrop · v20260731065814-full.1dc6f849
128 ms — deklarationer (db)
0 ms — hämta statistik (cache)
162 ms — hämta tråd, inlägg och bilagor (db)
123 ms — ändringar (db)