Skip to content
This repository has been archived by the owner on Jan 7, 2021. It is now read-only.

Commit

Permalink
Remove IDisposable from XmlObject.
Browse files Browse the repository at this point in the history
  • Loading branch information
AraHaan committed Sep 19, 2018
1 parent 102c96d commit 6f9a540
Show file tree
Hide file tree
Showing 4 changed files with 5 additions and 143 deletions.
43 changes: 0 additions & 43 deletions XmlAbstraction.Test/XmlObjectUnitTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -31,50 +31,14 @@ public void TestClassReopenFile()
$"{Environment.CurrentDirectory}{Path.DirectorySeparatorChar}test.xml");
fstrm.Write(Encoding.UTF8.GetBytes(testXml), 0, testXml.Length);
fstrm.Dispose();
xmlObj.Dispose();
xmlObj = new XmlObject(
$"{Environment.CurrentDirectory}{Path.DirectorySeparatorChar}test.xml",
testXml);
NoThrows(() => xmlObj.ReopenFile());
xmlObj.Dispose();
File.Delete(
$"{Environment.CurrentDirectory}{Path.DirectorySeparatorChar}test.xml");
}

[Fact]
public void TestClassDoubleDispose()
{
var testXml = @"<?xml version=""1.0"" encoding=""utf-8"" ?>
<test>
</test>";
var xmlObj = new XmlObject(testXml);
xmlObj.Dispose();
xmlObj.Dispose();
}

[Fact]
public void TestClassDisposedExceptions()
{
var testXml = @"<?xml version=""1.0"" encoding=""utf-8"" ?>
<test>
</test>";
var xmlObj = new XmlObject(testXml);
xmlObj.Dispose();

// test to make sure that ObjectDisposedException is thrown.
Assert.ThrowsAny<ObjectDisposedException>(() => xmlObj.AddAttribute("test4", "test", "test"));
Assert.ThrowsAny<ObjectDisposedException>(() => xmlObj.Write("test", "test"));
Assert.ThrowsAny<ObjectDisposedException>(() => xmlObj.Write("test2", "test", "test"));
Assert.ThrowsAny<ObjectDisposedException>(() => xmlObj.Write("test3", "test31", new string[] { "test1", "test2", "test3" }));
Assert.ThrowsAny<ObjectDisposedException>(() => xmlObj.Read("test"));
Assert.ThrowsAny<ObjectDisposedException>(() => xmlObj.Read("test2", "test"));
Assert.ThrowsAny<ObjectDisposedException>(() => xmlObj.Read("test3", "test31", null));
Assert.ThrowsAny<ObjectDisposedException>(() => xmlObj.Delete("test"));
Assert.ThrowsAny<ObjectDisposedException>(() => xmlObj.Delete("test2", "test"));
Assert.ThrowsAny<ObjectDisposedException>(() => xmlObj.ReopenFile());
Assert.ThrowsAny<ObjectDisposedException>(() => xmlObj.Save());
}

[Fact]
public void TestClassEdits()
{
Expand All @@ -96,15 +60,12 @@ public void TestClassEdits()
Assert.ThrowsAny<InvalidOperationException>(() => xmlObj.Delete("test"));
Assert.ThrowsAny<InvalidOperationException>(() => xmlObj.Delete("test2", "test"));
Assert.ThrowsAny<InvalidOperationException>(() => xmlObj.ReopenFile());
xmlObj.Dispose();
xmlObj = new XmlObject(testXmlNoRoot);
// reopen data from a file.
xmlObj.Dispose();
var fstrm = File.Create(
$"{Environment.CurrentDirectory}{Path.DirectorySeparatorChar}test.xml");
fstrm.Write(Encoding.UTF8.GetBytes(testXml), 0, testXml.Length);
fstrm.Dispose();
xmlObj.Dispose();
xmlObj = new XmlObject(
$"{Environment.CurrentDirectory}{Path.DirectorySeparatorChar}test.xml",
testXml);
Expand All @@ -124,15 +85,11 @@ public void TestClassEdits()
NoThrows(() => xmlObj.Delete("test"));
Assert.ThrowsAny<ArgumentException>(() => xmlObj.Delete("test2", "test"));
NoThrows(() => xmlObj.Save());
xmlObj.Dispose();
File.Delete(
$"{Environment.CurrentDirectory}{Path.DirectorySeparatorChar}test.xml");
xmlObj = new XmlObject($"{Path.DirectorySeparatorChar}test.xml", testXml, true);
xmlObj.Dispose();
xmlObj = new XmlObject($"{Path.DirectorySeparatorChar}test.xml", testXml, true);
xmlObj.Dispose();
xmlObj = new XmlObject($"{Environment.CurrentDirectory}{Path.DirectorySeparatorChar}test.xml", testXml, true);
xmlObj.Dispose();
}
}
}
4 changes: 2 additions & 2 deletions XmlAbstraction/XmlAbstraction.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -8,15 +8,15 @@
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
<Authors>AraHaan</Authors>
<Company />
<Version>1.0.1</Version>
<Version>1.1.0</Version>
<Description>A library that contains a System.Xml and System.Xml.Linq abstraction class.</Description>
<Copyright>Copyright 2018</Copyright>
<PackageTags>XML</PackageTags>
<RepositoryType>git</RepositoryType>
<RepositoryUrl>https://github.com/AraHaan/XmlAbstraction/</RepositoryUrl>
<PackageProjectUrl>https://github.com/AraHaan/XmlAbstraction/</PackageProjectUrl>
<PackageLicenseUrl>https://github.com/AraHaan/XmlAbstraction/blob/master/LICENSE</PackageLicenseUrl>
<PackageReleaseNotes>A bit of changes and implemented TODOs and some fixes as well.</PackageReleaseNotes>
<PackageReleaseNotes>A breaking change removing IDisposable from XmlObject.</PackageReleaseNotes>
<PublishDocumentationFile>true</PublishDocumentationFile>
</PropertyGroup>

Expand Down
99 changes: 2 additions & 97 deletions XmlAbstraction/XmlObject.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ namespace XmlAbstraction
// Only the Save() method should do direct edits to the XDocument object of the class named "Doc".
// The rest should just use the dictionaries for the changes to be applied to the xml in the Save()
// method if the xml is not read-only. I did this to support read only memory access of xml.
public class XmlObject : IDisposable
public class XmlObject
{
/// <summary>
/// Initializes a new instance of the <see cref="XmlObject"/> class
Expand Down Expand Up @@ -113,11 +113,6 @@ public XmlObject(string xmlfilename, string fallbackxmlcontent, bool saveToCurre
this.Doc = (fileSize > 0) ? XDocument.Load(xmlfilename) : XDocument.Parse(fallbackxmlcontent);
}

/// <summary>
/// Gets a value indicating whether the <see cref="XmlObject"/> is disposed.
/// </summary>
public bool IsDisposed { get; private set; } = false;

private object ObjLock { get; set; }

private XDocument Doc { get; set; }
Expand Down Expand Up @@ -181,15 +176,9 @@ private bool HasChangedExternally
/// but only if it has changed. If the file was not saved it
/// will be saved first.
/// </summary>
/// <exception cref="ObjectDisposedException"><see cref="XmlObject"/> is disposed.</exception>
/// <exception cref="InvalidOperationException">Cannot reopen on read-only instances.</exception>
public void ReopenFile()
{
if (this.IsDisposed)
{
throw new ObjectDisposedException(nameof(XmlObject));
}

if (!this.CachedXmlfilename.Equals(":memory"))
{
this.Save();
Expand All @@ -202,27 +191,21 @@ public void ReopenFile()
}

/// <summary>
/// Adds or edits an attribute in an Element and sets it's value in the XMLObject.
/// Adds or edits an attribute in an Element and sets it's value in the <see cref="XmlObject"/>.
///
/// This method can also remove the attribute by setting the value to null.
///
/// If Element does not exist yet it will be created automatically with an
/// empty value as well as making the attribute as if the Element was
/// pre-added before calling this function.
/// </summary>
/// <exception cref="ObjectDisposedException"><see cref="XmlObject"/> is disposed.</exception>
/// <exception cref="Exception">Attribute already exists in the xml file.</exception>
/// <exception cref="InvalidOperationException">When called from a read-only instance.</exception>
/// <param name="elementname">The name of the element to add a attribute to.</param>
/// <param name="attributename">The name of the attribute to add.</param>
/// <param name="attributevalue">The value of the attribute.</param>
public void AddAttribute(string elementname, string attributename, object attributevalue)
{
if (this.IsDisposed)
{
throw new ObjectDisposedException(nameof(XmlObject));
}

if (!this.CachedXmlfilename.Equals(":memory"))
{
var elem = this.Doc.Root.Element(elementname);
Expand Down Expand Up @@ -331,17 +314,11 @@ public void AddAttribute(string elementname, string attributename, object attrib
///
/// If Element does not exist yet it will be created automatically.
/// </summary>
/// <exception cref="ObjectDisposedException"><see cref="XmlObject"/> is disposed.</exception>
/// <exception cref="InvalidOperationException">When called from a read-only instance.</exception>
/// <param name="elementname">The name of the element to write to or create.</param>
/// <param name="value">The value for the element.</param>
public void Write(string elementname, string value)
{
if (this.IsDisposed)
{
throw new ObjectDisposedException(nameof(XmlObject));
}

if (!this.CachedXmlfilename.Equals(":memory"))
{
var elem = this.Doc.Root.Element(elementname);
Expand Down Expand Up @@ -396,7 +373,6 @@ public void Write(string elementname, string value)
///
/// If Element does not exist yet it will be created automatically.
/// </summary>
/// <exception cref="ObjectDisposedException"><see cref="XmlObject"/> is disposed.</exception>
/// <exception cref="Exception">Attribute already exists in the xml file.</exception>
/// <exception cref="InvalidOperationException">When called from a read-only instance.</exception>
/// <param name="elementname">
Expand All @@ -407,11 +383,6 @@ public void Write(string elementname, string value)
/// <param name="attributevalue">The value of the attribute to use.</param>
public void Write(string elementname, string attributename, string attributevalue)
{
if (this.IsDisposed)
{
throw new ObjectDisposedException(nameof(XmlObject));
}

if (!this.CachedXmlfilename.Equals(":memory"))
{
this.AddAttribute(elementname, attributename, attributevalue);
Expand All @@ -428,18 +399,12 @@ public void Write(string elementname, string attributename, string attributevalu
///
/// If Elements do not exist yet they will be created automatically.
/// </summary>
/// <exception cref="ObjectDisposedException"><see cref="XmlObject"/> is disposed.</exception>
/// <exception cref="InvalidOperationException">When called from a read-only instance.</exception>
/// <param name="parentelementname">parrent element name of the subelement.</param>
/// <param name="elementname">The name to use when writing subelement(s).</param>
/// <param name="values">The array of values to use for the subelement(s).</param>
public void Write(string parentelementname, string elementname, string[] values)
{
if (this.IsDisposed)
{
throw new ObjectDisposedException(nameof(XmlObject));
}

if (!this.CachedXmlfilename.Equals(":memory"))
{
var elem = this.Doc.Root.Element(parentelementname);
Expand Down Expand Up @@ -490,17 +455,11 @@ public void Write(string parentelementname, string elementname, string[] values)
///
/// If Element does not exist yet it will be created automatically with an empty value.
/// </summary>
/// <exception cref="ObjectDisposedException"><see cref="XmlObject"/> is disposed.</exception>
/// <exception cref="InvalidOperationException">When the Element does not exist in a read-only instance.</exception>
/// <param name="elementname">The element name to read the value from.</param>
/// <returns>The value of the input element or <see cref="string.Empty"/>.</returns>
public string Read(string elementname)
{
if (this.IsDisposed)
{
throw new ObjectDisposedException(nameof(XmlObject));
}

var elem = this.Doc.Root.Element(elementname);
if (elem != null
|| this.ElementsAdded.ContainsKey(elementname)
Expand Down Expand Up @@ -528,18 +487,12 @@ public string Read(string elementname)
/// If Element and the attribute does not exist yet it will be created automatically
/// with an empty value.
/// </summary>
/// <exception cref="ObjectDisposedException"><see cref="XmlObject"/> is disposed.</exception>
/// <exception cref="InvalidOperationException">When the Element does not exist in a read-only instance.</exception>
/// <param name="elementname">The element name to get the value of a attribute.</param>
/// <param name="attributename">The name of the attribute to get the value of.</param>
/// <returns>The value of the input element or <see cref="string.Empty"/>.</returns>
public string Read(string elementname, string attributename)
{
if (this.IsDisposed)
{
throw new ObjectDisposedException(nameof(XmlObject));
}

var elem = this.Doc.Root.Element(elementname);
if (elem == null)
{
Expand Down Expand Up @@ -583,7 +536,6 @@ public string Read(string elementname, string attributename)
/// If Parent Element does not exist yet it will be created automatically
/// with an empty value. In that case an empty string array is returned.
/// </summary>
/// <exception cref="ObjectDisposedException"><see cref="XmlObject"/> is disposed.</exception>
/// <exception cref="InvalidOperationException">When the Element does not exist in a read-only instance.</exception>
/// <param name="parentelementname">The name of the parrent element of the subelement(s).</param>
/// <param name="elementname">The name of the subelements to get their values.</param>
Expand All @@ -596,11 +548,6 @@ public string Read(string elementname, string attributename)
/// </returns>
public string[] Read(string parentelementname, string elementname, object unused = null)
{
if (this.IsDisposed)
{
throw new ObjectDisposedException(nameof(XmlObject));
}

var elem = this.Doc.Descendants(parentelementname);
var strarray = new string[] { };
foreach (var element in elem)
Expand All @@ -627,17 +574,11 @@ public string[] Read(string parentelementname, string elementname, object unused
/// Deletes an xml element using the element name.
/// Can also delete not only the parrent element but also subelements with it.
/// </summary>
/// <exception cref="ObjectDisposedException"><see cref="XmlObject"/> is disposed.</exception>
/// <exception cref="ArgumentException">elementname does not exist in the xml or in pending edits.</exception>
/// <exception cref="InvalidOperationException">When the object is a read-only instance.</exception>
/// <param name="elementname">The element name of the element to delete.</param>
public void Delete(string elementname)
{
if (this.IsDisposed)
{
throw new ObjectDisposedException(nameof(XmlObject));
}

if (!this.CachedXmlfilename.Equals(":memory"))
{
var elem = this.Doc.Root.Element(elementname);
Expand Down Expand Up @@ -667,18 +608,12 @@ public void Delete(string elementname)
/// <summary>
/// Removes an xml attribute using the element name and the name of the attribute.
/// </summary>
/// <exception cref="ObjectDisposedException"><see cref="XmlObject"/> is disposed.</exception>
/// <exception cref="ArgumentException">elementname or attributename does not exist in the xml or in pending edits.</exception>
/// <exception cref="InvalidOperationException">When the object is a read-only instance.</exception>
/// <param name="elementname">The element name that has the attribute to delete.</param>
/// <param name="attributename">The name of the attribute to delete.</param>
public void Delete(string elementname, string attributename)
{
if (this.IsDisposed)
{
throw new ObjectDisposedException(nameof(XmlObject));
}

if (!this.CachedXmlfilename.Equals(":memory"))
{
var elem = this.Doc.Root.Element(elementname);
Expand Down Expand Up @@ -731,19 +666,13 @@ public void Delete(string elementname, string attributename)
/// <summary>
/// Saves the underlying XML file if it changed.
/// </summary>
/// <exception cref="ObjectDisposedException"><see cref="XmlObject"/> is disposed.</exception>
public void Save()
{
// do not save in memory xml. It should be read only.
if (!this.CachedXmlfilename.Equals(":memory"))
{
lock (this.ObjLock)
{
if (this.IsDisposed)
{
throw new ObjectDisposedException(nameof(XmlObject));
}

if (this.HasChangedExternally && this.Exists)
{
// reopen file to apply changes at runtime to it.
Expand Down Expand Up @@ -831,11 +760,6 @@ public void Save()
}
}

/// <summary>
/// Disposes of the <see cref="XmlObject"/> and saves the underlying XML file if it changed.
/// </summary>
public void Dispose() => this.Dispose(true);

// Summary:
// Adds an Element to the XmlObject but verifies it does not exist first.
//
Expand Down Expand Up @@ -898,25 +822,6 @@ private void SaveAddedSubelements(XElement xElement, XmlElementData elemdata)
}
}

private void Dispose(bool disposing)
{
if (!this.IsDisposed)
{
this.Save();
this.Exists = false;
this.HasChanged = false;

// remove everything from the Lists/Dictonaries then destroy them.
this.ElementsAdded = null;
this.ElementsEdits = null;
this.ElementAttributesDeleted = null;
this.ElementsDeleted = null;
this.Doc = null;
this.CachedXmlfilename = string.Empty;
this.IsDisposed = true;
}
}

private class XmlAttributeData
{
internal string AttributeName { get; set; } = string.Empty;
Expand Down
2 changes: 1 addition & 1 deletion appveyor.yml
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
version: 1.0.1.0-alpha{build}
version: 1.1.0.0-alpha{build}
branches:
only:
- master
Expand Down

0 comments on commit 6f9a540

Please sign in to comment.