如何以其他方式编写使用块?

时间:2014-02-04 07:43:42

标签: c# c#-4.0 idisposable using using-statement

我有一个使用Windows窗体中不同方法的类。在我的测试代码中,我用它来创建一个新的OpenXML文档:

using (WordprocessingDocument package = WordprocessingDocument.Create(docName, WordprocessingDocumentType.Document))

但这似乎不适用于多种方法。我该如何解决?没有使用它就无法工作,所以经过一些研究后我发现这个课程是IDisposable。

但我现在有2个需求:

1)如果文件存在,则必须打开文档而不是创建新文件。

2)docName包含他要保存的文件的路径,必须可以在块中使用,如上所示。

有办法做到这一点吗?

这是我现在的代码:

using System;
using System.IO;
using System.Windows.Forms;
using DocumentFormat.OpenXml;
using DocumentFormat.OpenXml.Packaging;
using DocumentFormat.OpenXml.Wordprocessing;

namespace WordExample
{
    public partial class Word : Form
    {
        private string _docName = Environment.GetFolderPath(Environment.SpecialFolder.Desktop) + @"\xxx2.docx";
        private WordprocessingDocument _package;
        private Document _doc;
        private Body _body;

        public Word()
        {
            InitializeComponent();
            /*if (File.Exists(_docName))
            {
                _package = WordprocessingDocument.Open(_docName, false);
                _doc = _package.MainDocumentPart.Document;
                _body = _doc.Body;
            }
            else
            {
                _package = WordprocessingDocument.Create(_docName, WordprocessingDocumentType.Document);
                _package.AddMainDocumentPart();
                _doc = _package.MainDocumentPart.Document;
                _body = new Body();
            }*/

            _package = WordprocessingDocument.Create(_docName, WordprocessingDocumentType.Document);
            _package.AddMainDocumentPart();
            _doc = new Document();
            _body = new Body();
        }

        private void Word_Load(object sender, EventArgs e)
        {

        }

        private void btnAddParagraph_Click(object sender, EventArgs e)
        {
            /*Paragraph p = new Paragraph();
            Text t = new Text(txtTekstParagraaf.Text);
            Run r = new Run();
            RunProperties rPr = new RunProperties();
            if (chkBold.Checked)
            {
                Bold b = new Bold();
                rPr.Append(b);
            }
            if (chkItalic.Checked)
            {
                Italic b = new Italic();
                rPr.Append(b);
            }
            if (chkUnderline.Checked)
            {
                Underline b = new Underline();
                rPr.Append(b);
            }
            //RunProperties
            //r.PrependChild<RunProperties>(rPr);
            r.PrependChild(rPr);
            r.AppendChild(t);
            p.AppendChild(r);
            _body.AppendChild(p);*/
            Save();
        }

        private void Save()
        {
            _doc.AppendChild(_body);
            _package.MainDocumentPart.Document = _doc;

            // Save changes to the main document part. 
            _package.MainDocumentPart.Document.Save();
        }
    }
}

但是,此代码在尝试打开创建的文档时以及当我尝试打开文档而不是创建文档时会生成错误。

3 个答案:

答案 0 :(得分:3)

您可以尝试在此处使用三元运算符

using (WordprocessingDocument package = File.Exists(docName) ? 
         WordprocessingDocument.Create(docName, WordprocessingDocumentType.Document) :
         WordprocessingDocument.Open(docName, WordprocessingDocumentType.Document)) {
  ...
}

答案 1 :(得分:2)

  

如果文件存在,则必须打开文档而不是创建新文件。

那么为什么不使用if声明?

if(File.Exists(docName))
{
    using(var package = ..) // open file
    {
       ...  
    }
}
else
{
   using(var package = ..) // create file
   {
       ...  
   }
}

答案 2 :(得分:1)

您不必在using语句中直接实例化变量。您可以将创建移动到单独的方法:

private WordprocessingDocument GetPackage(string docName)
{
    var docType = WordprocessingDocumentType.Document;

    if (File.Exists(docName))
       return WordprocessingDocument.Open(docName, docType);

    return WordprocessingDocument.Create(docName, docType);
}

现在您的代码将如下所示:

using(var package = GetPackage(docName))
{
   // ...
}

更新:如果你想在所有类的方法中重用一次性依赖(正如你在评论中所述),你应该按类来实现IDisposale,它保存一次性依赖,并在你处理类时处理这种依赖: / p>

public class Foo : IDisposable
{
    private readonly WordprocessingDocument _package;

    public Foo()
    {
        _package = GetPackage(docName); // implemented as above
    }

    public void Method1()
    {
       // use _package without `using` block
    }

    public void Method2()
    {
       // use _package without `using` block
    }

    public void Dispose()
    {
        if (_package != null)
            _package.Dispose();
    }
}

然后将Foo的实例包装到using块中:

using(var foo = new Foo()) // _package created here
{
    foo.Method1(); // same _package instance used by both methods
    foo.Method2();
} // _package will be disposed here