Benutzerdefinierte SDK-Features

Features im Open XML SDK sind ab Version 2.14.0 verfügbar, sodass Verhalten und Zustand im Dokument oder Teil enthalten und angepasst werden können, ohne das enthaltende Paket oder Teil erneut zu implementieren. Der Zugriff erfolgt über Features die -Eigenschaft für Pakete, Teile und Elemente.

Dies ist eine Implementierung des Strategiemusters , das es einfach macht, das Verhalten im Fly-Betrieb zu ersetzen. Es wird nach den Anforderungsfeatures in ASP.NET Core modelliert.

Featurevererbung

Pakete, Teile und Elemente verfügen alle über eine eigene Featuresammlung. Sie erben jedoch auch den enthaltenden Teil und das Paket, wenn es verfügbar ist.

Um dies hervorzuheben, sehen Sie sich den folgenden Testfall an:

OpenXmlPackage package = /* Create a package */;

var packageFeature = new PrivateFeature();
package.Features.Set<PrivateFeature>(packageFeature);

var part = package.GetPartById("existingPart");
Assert.Same(part.Features.GetRequired<PrivateFeature>(), package.Features.GetRequired<PrivateFeature>());

part.Features.Set<PrivateFeature>(new());
Assert.NotSame(part.Features.GetRequired<PrivateFeature>(), package.Features.GetRequired<PrivateFeature>());


private sealed class PrivateFeature
{
}

Hinweis

Die Featureauflistung für Elemente ist schreibgeschützt. Dies ist auf Speicherprobleme zurückzuführen, wenn es beschreibbar gemacht wird. Wenn dies erforderlich ist, wenden Sie sich bitte an https://github.com/dotnet/open-xml-sdk , um uns Ihr Szenario mitzuteilen.

Visualisieren registrierter Features

Die im Lieferumfang enthaltenen Implementierungen von bieten eine hilfreiche Debugansicht, mit der IFeatureCollection Sie sehen können, welche Features verfügbar sind und welche Eigenschaften/Felder sie aufweisen:

Debugansicht für Features

Verfügbare Features

Die derzeit verfügbaren Features werden unten beschrieben und in welchem Umfang sie verfügbar sind:

IDisposableFeature

Dieses Feature ermöglicht das Registrieren von Aktionen, die ausgeführt werden müssen, wenn ein Paket oder ein Teil zerstört oder verworfen wird:

OpenXmlPackage package = GetSomePackage();
package.Features.Get<IDisposableFeature>().Register(() => /* Some action that is called when the package is disposed */);

OpenXmlPart part = GetSomePart();
part.Features.Get<IDisposableFeature>().Register(() => /* Some action that is called when the part is removed or closed */);

Pakete und Teile verfügen über eigene Implementierungen dieses Features. Elemente rufen das Feature für ihren enthaltenden Teil ab, sofern verfügbar.

IPackageEventsFeature

Dieses Feature ermöglicht das Abrufen von Ereignisbenachrichtigungen, wenn ein Paket geändert wird:

OpenXmlPackage package = GetSomePackage();
package.TryAddPackageEventsFeature();

var feature = package.Features.GetRequired<IPackageEventsFeature>();

Hinweis

Es kann vorkommen, dass das Paket geändert wird, aber kein Ereignis ausgelöst wird. Es wurden nicht alle Bereiche identifiziert, in denen es sinnvoll wäre, ein Ereignis auszulösen. Melden Sie ein Problem, wenn Sie eines finden.

IPartEventsFeature

Dieses Feature ermöglicht das Abrufen von Ereignisbenachrichtigungen, wenn ein Ereignis erstellt wird. Dies ist ein Feature, das dem Teil oder Paket hinzugefügt wird:

OpenXmlPart part = GetSomePackage();
package.AddPartEventsFeature();

var feature = part.Features.GetRequired<IPartEventsFeature>();

Gehen Sie im Allgemeinen davon aus, dass es möglicherweise eine Singletonimplementierung für die Ereignisse gibt, und überprüfen Sie, ob der Teil der richtige Teil ist.

Hinweis

Es kann vorkommen, dass der Teil geändert wird, aber kein Ereignis ausgelöst wird. Es wurden nicht alle Bereiche identifiziert, in denen es sinnvoll wäre, ein Ereignis auszulösen. Melden Sie ein Problem, wenn Sie eines finden.

IPartRootEventsFeature

Dieses Feature ermöglicht das Abrufen von Ereignisbenachrichtigungen, wenn ein Teilstamm geändert/geladen/erstellt wird usw. Dies ist ein Feature, das dem Feature auf Teileebene hinzugefügt wird:

OpenXmlPart part = GetSomePart();
part.AddPartRootEventsFeature();

var feature = part.Features.GetRequired<IPartRootEventsFeature>();

Gehen Sie im Allgemeinen davon aus, dass es möglicherweise eine Singletonimplementierung für die Ereignisse gibt, und überprüfen Sie, ob der Teil der richtige Teil ist.

Hinweis

Es kann vorkommen, dass der Stamm des Teils geändert wird, aber kein Ereignis ausgelöst wird. Es wurden nicht alle Bereiche identifiziert, in denen es sinnvoll wäre, ein Ereignis auszulösen. Melden Sie ein Problem, wenn Sie eines finden.

IRandomNumberGeneratorFeature

Dieses Feature ermöglicht es einem freigegebenen Dienst, Zufallszahlen zu generieren und ein Array zu füllen.

IParagraphIdGeneratorFeature

Dieses Feature ermöglicht die Auffüllung und Nachverfolgung von Elementen, die Absatz-IDs enthalten. Dadurch wird standardmäßig die Eindeutigkeit von Werten sichergestellt und sichergestellt, dass vorhandene Werte gemäß den Einschränkungen des Standards gültig sind. So verwenden Sie dieses Feature:

WordprocessingDocument document = CreateWordDocument();
document.TryAddParagraphIdFeature();

var part = doc.AddMainDocumentPart();
var body = new Body();
part.Document = new Document(body);

var p = new Paragraph();
body.AddChild(p); // After adding p.ParagraphId will be set to a unique, valid value

Dieses Feature kann auch verwendet werden, um die Eindeutigkeit mehrerer Dokumente mit einer geringfügigen Änderung sicherzustellen:

using var doc1 = CreateDocument1();
using var doc2 = CreateDocument2();

var shared = doc1
    .AddSharedParagraphIdFeature()
    .Add(doc2);

// Add item to doc1
var part1 = doc1.AddMainDocumentPart();
var body1 = new Body();
var p1 = new Paragraph();
part1.Document = new Document(body1);
body1.AddChild(p1);

// Add item with same ID to doc2
var part2 = doc2.AddMainDocumentPart();
var body2 = new Body();
var p2 = new Paragraph { ParagraphId = p1.ParagraphId };
part2.Document = new Document(body2);
body2.AddChild(p2);

// Assert
Assert.NotEqual(p1.ParagraphId, p2.ParagraphId);
Assert.Equal(2, shared.Count);

IPartRootXElementFeature

Dieses Feature ermöglicht den Betrieb auf einem OpenXmlPart durch Die Verwendung von XLinq-Features und das direkte Bearbeiten von XElement Knoten.

OpenXmlPart part = GetSomePart();

var node = new(W.document, new XAttribute(XNamespace.Xmlns + "w", W.w),
    new XElement(W.body,
        new XElement(W.p,
            new XElement(W.r,
                new XElement(W.t, "Hello World!")))));

part.SetXElement(node);

Dies XElement wird zwischengespeichert, wird aber bei einer Änderung mit dem zugrunde liegenden Teil synchronisiert.