Звонит файла писать в распоряжаться приемлемо?


class HtmlLogger:ILogger,IDisposable 
{
    private System.IO.StreamWriter  _file;
    private bool _disposed;

    public HtmlLogger()
    {
        _disposed = false;
        _file = new StreamWriter(@"somepath");
        _file.Write("<HTML><BODY>");
    }

    public void Log(string message)
    {
        _file.Write("<DIV>{0}</DIV>", message);
    }

    public void Dispose()
    {
        Dispose(true);
        GC.SuppressFinalize(this);
    }

    protected virtual void Dispose(bool disposing)
    {
        if (!_disposed)
        {
            if (disposing)
            {
                if (_file != null)
                {
                    _file.Write("</BODY></HTML>");
                    _file.Flush();
                    _file.Dispose();
                }

            }
            _file = null;
            _disposed = true;
        }
    }
}


1117
3
задан 2 октября 2011 в 06:10 Источник Поделиться
Комментарии
2 ответа

На мой взгляд, вы должны сделать что-нибудь в распоряжаться , кроме закрытия объектов.
Может, пользователь вашей библиотеки не распоряжаться , а просто устанавливается базовое значение null. Закрывающие Теги никогда не будут написаны, но starttags бы. Поэтому было бы недопустимый XML-файл, который является плохое поведение на мой взгляд.

Я хотел реализовать метод для явного сохранения, так что пользователь класса может спасти, когда он хочет, и даже может продолжать ведение журнала после сохранения. Поэтому я также хотел бы использовать объект XmlDocument, поэтому я не придется иметь дело с правильности XML и файл сохранения.

class HtmlLogger:ILogger,IDisposable 
{
private System.IO.StreamWriter _file;
private bool _disposed;

public HtmlLogger()
{
_disposed = false;
_file = new StreamWriter(@"somepath");
_file.Write("<HTML><BODY>");
}

~HtmlLogger{
Dispose(false);
}

public void Log(string message)
{
_file.Write("<DIV>{0}</DIV>", message);
}

public void Dispose()
{
Dispose(true);
}

private void Dispose(bool disposing){
if(_disposed)
return;

if(disposing){
_disposed=true;
}

if(file != null)
{
_file.Flush();
_file.Close();
_file= null;
}
}

protected virtual void Save()
{
if (_file != null)
{
_file.Write("</BODY></HTML>");
_file.Flush();
}
}
}
}


  1. Я бы добавил деструктор и флеш/закрываем файл в любом случае, просто убедитесь, что другие программы могут снова открыть его (если это правильный XML тогда) и нет ссылки на файл сохраняются.

  2. Что происходит с XML, если кто-то звонит:

    Log("<SuperMessage>");
    Log("Ü");

1
ответ дан 2 октября 2011 в 08:10 Источник Поделиться

Я думаю, что это хорошая идея, чтобы использовать существующие классы, я уже сделал некоторые из refacorings вместе с некоторые дизайнерские решения. Для получения дополнительной информации, пожалуйста, прочитайте эту книгу:

Редактировать: я думаю, что явные команда (открыть журнал, писать что-то и закрыть его), прежде чем утилизировать журнал объект гораздо более читабельным, легко понять и поддерживать позже, чем impementing метод Dispose паттерна в другой объект (так вы получите как минимум два объекта для управления жизненным циклом: пользовательский класс, и модулю записи StreamWriter класс - который сломает Эйнштейна правило, - это просто не хорошо для контроля 2 объекты, когда можно просто контролировать один). В частности, это будет справедливо, когда новые контракты будут применены позже в коде. Одноразовые модели является тяжелый для такой простой задачи. Кроме того, в качестве преимуществ использования одного объекта управления, а, следовательно, - очень упрощенная логика, это легче контролировать жизнь писателя объекте журнала. Во-вторых, простой класс с хорошим и бвести конструкция может быть легко расширена, чтобы отблагодарить за дополнительную логику и не будет, скорее всего, содержит какие-либо из недостатков в будущем.

public interface IHTMLLogger
{
ILogWriter CreateHTMLLogWriter(string filePath);
}

public interface ILogWriter : IDisposable
{
void OpenLog();
void WriteLog(string message);
void CloseLog();
}

public class HtmlLogger : IHTMLLogger
{
public class HTMLLogWriter : StreamWriter, ILogWriter
{
public HTMLLogWriter(string filePath)
: base(filePath)
{
}
public void WriteLog(string message)
{
base.Write(string.Format("<DIV>{0}</DIV>", message));
}
public void OpenLog()
{
base.Write("<HTML><BODY>");
}
public void CloseLog()
{
base.Write("</BODY></HTML>");
}
}

public ILogWriter CreateHTMLLogWriter(string filePath)
{
return new HTMLLogWriter(filePath);
}
}

Редактировать: как вы видите, я могу легко интегрировать новые кодирования логики для кодирования любых строковых данных:

public interface IHTMLEncoder
{
string Encode(string message);
}

public interface IHTMLLogger
{
ILogWriter CreateHTMLLogWriter(string filePath);
}

public interface ILogWriter : IDisposable
{
void OpenLog();
void WriteLog(string message);
void CloseLog();
}

public class HtmlLogger : IHTMLLogger
{
public class HTMLEncoder : IHTMLEncoder
{
public string Encode(string message)
{
return Convert.ToBase64String(Encoding.UTF8.GetBytes(message.ToCharArray()));
}
}
public class HTMLLogWriter : StreamWriter, ILogWriter
{
private IHTMLEncoder _encoder;
public HTMLLogWriter(string filePath, IHTMLEncoder encoder)
: base(filePath)
{
_encoder = encoder;
}
public void WriteLog(string message)
{
base.Write(string.Format("<DIV>{0}</DIV>", _encoder.Encode(message)));
}
public void OpenLog()
{
base.Write("<HTML><BODY>");
}
public void CloseLog()
{
base.Write("</BODY></HTML>");
}
}
public ILogWriter CreateHTMLLogWriter(string filePath)
{
return new HTMLLogWriter(filePath, new HTMLEncoder());
}
}

Образец:

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Configuration;
using System.Runtime.Serialization;
using System.Security.Permissions;
using System.IO;
using System.Diagnostics;

namespace WindowsFormsApplication1
{
public partial class Form1 : Form
{
private static IHTMLLogger logger = new HtmlLogger();
private ILogWriter logWriter;

public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
logWriter = logger.CreateHTMLLogWriter(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "html.log"));
logWriter.OpenLog();

this.Location = UserSettings.Default.FormLocation;
this.Size = UserSettings.Default.FormSize;
this.textBox1.Text = UserSettings.Default.ProcessPath;
}

private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
UserSettings.Default.FormLocation = this.Location;
UserSettings.Default.FormSize = this.Size;
UserSettings.Default.ProcessPath = this.textBox1.Text;
UserSettings.Default.Save();

logWriter.CloseLog();
logWriter.Dispose();

MessageBox.Show(File.ReadAllText(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "html.log")));
}

private void textBox1_TextChanged(object sender, EventArgs e)
{
UserSettings.Default.ProcessPath = this.textBox1.Text;
logWriter.WriteLog(this.textBox1.Text);
}
}

[SettingsSerializeAs(SettingsSerializeAs.Xml)]
[Serializable]
public sealed class UserSettings : ApplicationSettingsBase
{
private const string FormLocationProperty = "FormLocation";
private const string FormSizeProperty = "FormSize";
private const string ProcessPathProperty = "ProcessPath";

private UserSettings() { }

private static UserSettings _defaultInstance = new UserSettings();

public static UserSettings Default { get { return _defaultInstance; } }

[UserScopedSetting()]
[DefaultSettingValue("0, 0")]
public Point FormLocation
{
get { return (Point)(this[FormLocationProperty]); }
set { this[FormLocationProperty] = value; }
}

[UserScopedSetting()]
[DefaultSettingValue("300, 300")]
public Size FormSize
{
get { return (Size)this[FormSizeProperty]; }
set { this[FormSizeProperty] = value; }
}

[UserScopedSetting]
[DefaultSettingValue("")]
public string ProcessPath
{
get { return (string)this[ProcessPathProperty]; }
set { this[ProcessPathProperty] = value; }
}
}
}

1
ответ дан 3 октября 2011 в 07:10 Источник Поделиться