简体   繁体   中英

Creating class instances in a list

What I'm trying to accomplish is this:

The class Logger should declare a collection of LogMedia as a member variable, and only needs to declare a single function: void LogException( Exception ex ) . Inside this function, you should loop through all LogMedia instances, and call a virtual function defined in each one.

What I'm having trouble understanding is how can I implement a loop that goes through all these instances. Or maybe rather, how do I create these instances?

Logger Class

public class Logger
    {
       static List<LogMedia> m_loggers = new List<LogMedia>();

         **//Should I create som instances here?**
        public static void LogException(Exception ex)
        {
            foreach(var i in m_loggers)
            {
                i.LogMessage(ex.Message + Environment.NewLine);
            }
        }

        }
    }

LogMediaClass* :Then I was to create the class logmedia and three other classes where"Each of the derived classes should then override this function in the LogMedia class. How can I create instances of these three classes such that I can loop through them as shown in Logger?*

public class LogMedia
    {
        public virtual void LogMessage(string Message) { } //virtual function that doesen't do anything

    }
    public class OutputWindowLogMedia : LogMedia
    {
        public override void LogMessage(string Message)
        {
            System.Diagnostics.Debug.WriteLine(Message);
        }
    }
    class TextFileLogMedia : LogMedia
    {
        public override void LogMessage(string Message)
        {
            StreamWriter writer = new StreamWriter("C:\\Temp\\xxx\\xxxx.txt");
            writer.WriteLine(Message + " the error occured at: ");
            writer.Close();
        }
    }
    class EmailLogMedia : LogMedia
    {
        public override void LogMessage(string Message)
        {


            const string senderID = "xxx@gmail.com"; // use sender's email id here..
            const string toAddress = "xxx@some.com";
            const string senderPassword = "xxxx"; // sender password here...
            try
            {
                SmtpClient smtp = new SmtpClient
                {
                    Host = "smtp.gmail.com", // smtp server address here...
                    Port = 587,
                    EnableSsl = true,
                    DeliveryMethod = SmtpDeliveryMethod.Network,
                    Credentials = new System.Net.NetworkCredential(senderID, senderPassword),
                    Timeout = 30000,
                };
                MailMessage message = new MailMessage(senderID, toAddress, "erroe", "error");
                smtp.Send(message);
            }
            catch (Exception ex)
            {
                Console.ForegroundColor = ConsoleColor.Red;
                Console.WriteLine("Error sending mail:" + ex.Message);
                Console.ResetColor();
            }

        }
    }

straight forward method:

public Logger()
{
    loggers.Add(new OutputWindowLogMedia ());
    loggers.Add(new TextFileLogMedia ());
    loggers.Add(new EmailLogMedia ());
}

If you want something more extensible look at MEF or just use log4net, which is configuration driven.

Please initialize in a static constructor .

Add all the loggers in there. It will be ensured that whenever LogException() is called the list is populated, seeing that the function is static.

Also just a side thought, do make the base LogMedia as abstract or favorably an interface .

Now there is a side -affect to this as well, whenever a new LogMedia is added sometime in the future, an Add call must be added in the static constructor.

This might induce bugs in big projects in maintainence, so to avoid that, add an InitializeAllLoggers() method in the static constructor and put the following code in it.

foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies().ToList())
{
    foreach (Type classType in assembly.GetTypes())
    {
         if (classType.IsClass
                    && !classType.IsAbstract
                    && classType.IsSubclassOf(typeof(LogMedia)))                     
         {
              m_loggers.Add(Activator.CreateInstance(classType) as LogMedia);
         }
    }
}

This will ensure that whenever a new type of LogMedia is created, its automatically added to the loggers list.

The common approach is:

  1. Add Register and Unregister static methods to Logger class. The methods just adds / removes the member to m_loggers list.
  2. Your code uses the methods to register / unregister loggers.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM