【问题标题】:Creating class instances in a list在列表中创建类实例
【发布时间】:2014-04-21 08:26:51
【问题描述】:

我想要完成的是:

Logger 类应该将LogMedia 的集合声明为成员变量,并且只需要声明一个函数:void LogException( Exception ex )。在这个函数内部,你应该遍历所有LogMedia实例,并调用每个实例中定义的虚函数。

我无法理解的是如何实现一个遍历所有这些实例的循环。或者更确切地说,我如何创建这些实例?

记录器类

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*:然后我要创建类 logmedia 和其他三个类,其中“每个派生类都应该在 LogMedia 类中覆盖这个函数。如何创建这三个的实例类,以便我可以遍历它们,如 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();
            }

        }
    }

【问题讨论】:

  • 两个切线相关的注释:1)为什么不使用抽象类/方法而不是没有基本实现的虚拟方法? 2) 您应该将 StreamWriter 包装在 using 语句中,以确保它被正确处理。
  • 您是否正在寻找一种方法来以编程方式查找和实例化从 LogMedia 派生的所有类?
  • 是的。我希望能够遍历覆盖/继承 Logmedia 类的所有类实例

标签: c# list class logging foreach


【解决方案1】:

请在静态构造函数中初始化。

在其中添加所有记录器。将确保每当调用 LogException() 时,都会填充列表,因为该函数是静态的。

也只是一个侧面的想法,将基本 LogMedia 设置为 abstract 或者最好是 interface

现在这也有一个副作用,无论将来何时添加新的 LogMedia,都必须在静态构造函数中添加 Add 调用。

这可能会导致大型项目在维护中出现错误,因此为避免这种情况,请在静态构造函数中添加InitializeAllLoggers() 方法并将以下代码放入其中。

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);
         }
    }
}

这将确保无论何时创建新类型的LogMedia,它都会自动添加到记录器列表中。

【讨论】:

  • 在静态构造函数中初始化?你能解释一下你的意思吗?我应该像我做的那样从 LogMeda 创建列表吗?然后将所有实例添加到列表中?没有?
  • Logger 类添加静态构造函数,如下所示:static Logger() {m_loggers.Add(new OutputWindowLogMedia()); m_loggers.Add(new TextFileLogMedia());m_loggers.Add(new EmailLogMedia());}
【解决方案2】:

直截了当的方法:

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

如果您想要更可扩展的东西,请查看 MEF 或只使用 log4net,它是配置驱动的。

【讨论】:

  • 我不能做到以下几点:m_loggers.Add(new emailLogMedia());但我得到了 m_logger 是一个字段但被用作类型的错误
  • 我的感觉告诉我,你是在类定义中而不是在构造函数中添加该行
【解决方案3】:

常见的做法是:

  1. 向 Logger 类添加 Register 和 Unregister 静态方法。这些方法只是将成员添加/删除到 m_loggers 列表中。
  2. 您的代码使用注册/注销记录器的方法。

【讨论】:

    猜你喜欢
    • 2017-12-18
    • 2017-05-31
    • 2013-12-02
    • 1970-01-01
    • 1970-01-01
    • 2020-06-28
    • 1970-01-01
    • 1970-01-01
    • 2015-11-19
    相关资源
    最近更新 更多