Added tests and made corrections to Opc interfaces

pull/119/head
dahall 2020-01-12 21:11:43 -07:00
parent 019fd00485
commit a98f49d582
2 changed files with 125 additions and 8 deletions

View File

@ -1,6 +1,10 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Runtime.InteropServices.ComTypes;
using Vanara.Extensions.Reflection;
using Vanara.InteropServices;
using static Vanara.PInvoke.Crypt32;
using static Vanara.PInvoke.UrlMon;
@ -59,10 +63,10 @@ namespace Vanara.PInvoke
public enum OPC_COMPRESSION_OPTIONS
{
/// <summary>Compression is turned off.</summary>
OPC_COMPRESSION_NONE,
OPC_COMPRESSION_NONE = -1,
/// <summary>Compression is optimized for a balance between size and performance.</summary>
OPC_COMPRESSION_NORMAL,
OPC_COMPRESSION_NORMAL = 0,
/// <summary>Compression is optimized for size.</summary>
OPC_COMPRESSION_MAXIMUM,
@ -261,7 +265,7 @@ namespace Vanara.PInvoke
/// The signature is not valid.Signature markup or signed package components might have been altered. Alternatively, the
/// signature might not exist in the current package.
/// </summary>
OPC_SIGNATURE_INVALID,
OPC_SIGNATURE_INVALID = -1,
}
/// <summary>Describes the read/write status of a stream.</summary>
@ -272,7 +276,7 @@ namespace Vanara.PInvoke
public enum OPC_STREAM_IO_MODE
{
/// <summary>Creates a read-only stream for loading an existing package.</summary>
OPC_STREAM_IO_READ,
OPC_STREAM_IO_READ = 1,
/// <summary>Creates a write-only stream for saving a new package.</summary>
OPC_STREAM_IO_WRITE,
@ -1670,7 +1674,7 @@ namespace Vanara.PInvoke
// LPCWSTR filename, OPC_STREAM_IO_MODE ioMode, LPSECURITY_ATTRIBUTES securityAttributes, DWORD dwFlagsAndAttributes, IStream
// **stream );
[PreserveSig]
HRESULT CreateStreamOnFile([MarshalAs(UnmanagedType.LPWStr)] string filename, OPC_STREAM_IO_MODE ioMode, SECURITY_ATTRIBUTES securityAttributes, FileFlagsAndAttributes dwFlagsAndAttributes, out IStream stream);
HRESULT CreateStreamOnFile([MarshalAs(UnmanagedType.LPWStr)] string filename, OPC_STREAM_IO_MODE ioMode, [Optional] SECURITY_ATTRIBUTES securityAttributes, FileFlagsAndAttributes dwFlagsAndAttributes, out IStream stream);
/// <summary>Creates a package object that represents an empty package.</summary>
/// <returns>A pointer to the IOpcPackage interface of the package object that represents an empty package.</returns>
@ -6798,5 +6802,67 @@ namespace Vanara.PInvoke
[PInvokeData("msopc.h", MSDNShortId = "0a265a0a-c109-4afc-a0ad-d3ee31757aa1")]
[ComImport, ClassInterface(ClassInterfaceType.None), Guid("6B2D6BA0-9F3E-4f27-920B-313CC426A39E")]
public class OpcFactory { }
/// <summary>Creates an <see cref="IEnumerator{T}"/> instance from one of the IOpcXXXEnumerator interface instances.</summary>
/// <typeparam name="TEnum">
/// The type of the enumerator interface. This interface must support the MoveNext, GetCurrent and Clone methods.
/// </typeparam>
/// <typeparam name="TElem">The type of the elemement interface returned as the parameter in TElem.GetCurrent.</typeparam>
/// <seealso cref="IEnumerator{T}"/>
public class OpcEnumerator<TEnum, TElem> : IEnumerator<TElem>
{
private MethodInfo getCurrent;
private MethodInfo moveNext;
private TEnum opcEnum;
/// <summary>Initializes a new instance of the <see cref="OpcEnumerator{TEnum, TElem}"/> class.</summary>
/// <param name="opcEnumerator">The opc enumerator.</param>
/// <exception cref="ArgumentNullException">opcEnumerator</exception>
/// <exception cref="ArgumentException">The type specified for TEnum is not a valid Opc Enumerator instance.</exception>
public OpcEnumerator(TEnum opcEnumerator)
{
opcEnum = opcEnumerator ?? throw new ArgumentNullException(nameof(opcEnumerator));
moveNext = typeof(TEnum).GetMethod("MoveNext");
getCurrent = typeof(TEnum).GetMethod("GetCurrent");
if (moveNext is null || getCurrent is null) throw new ArgumentException("The type specified for TEnum is not a valid Opc Enumerator instance.");
}
/// <summary>Gets the element in the collection at the current position of the enumerator.</summary>
public TElem Current
{
get
{
var p = new object[] { default(TElem) };
((HRESULT)getCurrent.Invoke(opcEnum, p)).ThrowIfFailed();
return (TElem)p[0];
}
}
/// <summary>Gets the element in the collection at the current position of the enumerator.</summary>
object IEnumerator.Current => Current;
/// <summary>Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.</summary>
public void Dispose() => Marshal.ReleaseComObject(opcEnum);
/// <summary>Advances the enumerator to the next element of the collection.</summary>
/// <returns>
/// <see langword="true"/> if the enumerator was successfully advanced to the next element; <see langword="false"/> if the
/// enumerator has passed the end of the collection.
/// </returns>
public bool MoveNext()
{
var p = new object[] { false };
((HRESULT)moveNext.Invoke(opcEnum, p)).ThrowIfFailed();
return (bool)p[0];
}
/// <summary>Sets the enumerator to its initial position, which is before the first element in the collection.</summary>
public void Reset()
{
var clone = opcEnum.InvokeMethod<TEnum>("Clone");
Marshal.ReleaseComObject(opcEnum);
opcEnum = clone;
}
}
}
}

View File

@ -1,10 +1,11 @@
using NUnit.Framework;
using System;
using System.Linq;
using System.Collections;
using System.Collections.Generic;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text;
using System.Threading;
using Vanara.Extensions;
using Vanara.Extensions.Reflection;
using Vanara.InteropServices;
using static Vanara.PInvoke.Opc;
@ -13,5 +14,55 @@ namespace Vanara.PInvoke.Tests
[TestFixture]
public class OpcTests
{
public IOpcFactory factory;
[OneTimeSetUp]
public void _Setup() => factory = new IOpcFactory();
[OneTimeTearDown]
public void _TearDown() => Marshal.ReleaseComObject(factory);
[Test]
public void LoadTest()
{
Assert.That(factory.CreateStreamOnFile(TestCaseSources.WordDoc, OPC_STREAM_IO_MODE.OPC_STREAM_IO_READ, null, 0, out var sourceFileStream), ResultIs.Successful);
using var psourceFileString = ComReleaserFactory.Create(sourceFileStream);
Assert.That(factory.ReadPackageFromStream(sourceFileStream, OPC_READ_FLAGS.OPC_CACHE_ON_ACCESS, out var outPackage), ResultIs.Successful);
using var poutPackage = ComReleaserFactory.Create(outPackage);
IOpcPartSet pset = null;
Assert.That(() => pset = outPackage.GetPartSet(), Throws.Nothing);
using var ppset = ComReleaserFactory.Create(pset);
IOpcPartEnumerator penum = null;
Assert.That(() => penum = pset.GetEnumerator(), Throws.Nothing);
using var ppenum = new OpcEnumerator<IOpcPartEnumerator, IOpcPart>(penum);
while (ppenum.MoveNext())
TestContext.WriteLine($"{ppenum.Current.GetContentType()}, {ppenum.Current.GetCompressionOptions()}");
TestContext.WriteLine();
IOpcRelationshipSet rset = null;
Assert.That(() => rset = outPackage.GetRelationshipSet(), Throws.Nothing);
using var prset = ComReleaserFactory.Create(rset);
IOpcRelationshipEnumerator renum = null;
Assert.That(() => renum = rset.GetEnumerator(), Throws.Nothing);
using var prenum = new OpcEnumerator<IOpcRelationshipEnumerator, IOpcRelationship>(renum);
while (prenum.MoveNext())
TestContext.WriteLine($"{prenum.Current.GetId()}, {prenum.Current.GetRelationshipType()}, {prenum.Current.GetTargetMode()}");
TestContext.WriteLine();
}
[Test]
public void RootTest()
{
IOpcUri rootUri = null;
Assert.That(() => rootUri = factory.CreatePackageRootUri(), Throws.Nothing);
Assert.That(rootUri, Is.Not.Null);
Marshal.ReleaseComObject(rootUri);
}
}
}