187 lines
5.1 KiB
Markdown
187 lines
5.1 KiB
Markdown
|
# Contents
|
||
|
|
||
|
The contents of a file may be stored as a component, however this increases the
|
||
|
memory pressure when Nitride works with hundreds or thousands of files. To
|
||
|
reduce this, memory is loaded on demand through an abstracted components such
|
||
|
as `IBinaryContent` and `ITextContent`.
|
||
|
|
||
|
## Exclusivity
|
||
|
|
||
|
The content interfaces are treated as *mutually exclusive* with each other by
|
||
|
extending the `IContent` interface. The intended reason for this is to have a
|
||
|
single source of data that doesn't go out of sync. Adding or setting
|
||
|
a `IBinaryContent` will remove the other content components in the entity, even
|
||
|
ones that are defined in other classes. In effect, all `IContent`
|
||
|
will be removed to ensure that. This is implemented via a number of extension
|
||
|
operations.
|
||
|
|
||
|
```c#
|
||
|
Entity entity;
|
||
|
IBinaryContent binaryContent;
|
||
|
ITextContent textContent;
|
||
|
|
||
|
entity.Add(binaryContent);
|
||
|
Assert.Equal(1, entity.Count);
|
||
|
Assert.True(entity.Has<IBinaryContent>());
|
||
|
Assert.True(entity.HasBinaryContent());
|
||
|
Assert.True(entity.HasContent());
|
||
|
|
||
|
entity.SetContent(textContent);
|
||
|
Assert.Equal(1, entity.Count);
|
||
|
Assert.False(entity.Has<IBinaryContent>());
|
||
|
Assert.False(entity.HasBinaryContent());
|
||
|
Assert.True(entity.Has<ITextContent>());
|
||
|
Assert.True(entity.HasTextContent());
|
||
|
Assert.True(entity.HasContent());
|
||
|
|
||
|
entity.RemoveContent();
|
||
|
Assert.Equal(0, entity.Count);
|
||
|
Assert.False(entity.Has<IBinaryContent>());
|
||
|
Assert.False(entity.HasBinaryContent());
|
||
|
Assert.False(entity.Has<ITextContent>());
|
||
|
Assert.False(entity.HasTextContent());
|
||
|
Assert.False(entity.HasContent());
|
||
|
```
|
||
|
|
||
|
This exclusivity can be ignored by using direct `Add<>`, `Set<>`, and
|
||
|
`Remove<>` methods on the entity. That would allow multiple content to be added
|
||
|
and removed at the same time.
|
||
|
|
||
|
```c#
|
||
|
Entity entity;
|
||
|
IBinaryContent binaryContent = entity.Get<IBinaryContent>();
|
||
|
using Stream binaryStream = binaryContent.GetStream();
|
||
|
using StreamReader binaryReader = new StreamReader(binaryStream);
|
||
|
var text = binaryReader.ReadToEnd();
|
||
|
var textContent = new StringTextContent(text);
|
||
|
|
||
|
var switchedEntity = entity
|
||
|
.Set<ITextContent>(textContent)
|
||
|
.Remove<IBinaryContent>();
|
||
|
Assert.Equal(1, switchedEntity.Count);
|
||
|
Assert.True(switchedEntity.Has<ITextContent>());
|
||
|
Assert.False(switchedEntity.Has<ITextContent>());
|
||
|
|
||
|
var mergedEntity = entity
|
||
|
.Set<ITextContent>(textContent);
|
||
|
Assert.Equal(2, switchedEntity.Count);
|
||
|
Assert.True(switchedEntity.Has<ITextContent>());
|
||
|
Assert.True(switchedEntity.Has<ITextContent>());
|
||
|
```
|
||
|
|
||
|
Implementing this with a parent interface (`IContent`) allows future content
|
||
|
providers, such as `IXmlContent` or other future content sources.
|
||
|
|
||
|
## IBinaryComponent
|
||
|
|
||
|
Most files start as only having access to binary content.
|
||
|
|
||
|
```c#
|
||
|
Entity entity;
|
||
|
IBinaryContent content = entity.Get<IBinaryContent>();
|
||
|
using Stream stream = content.GetStream();
|
||
|
```
|
||
|
|
||
|
There is no guarantee that the data behind the stream is loaded into memory or
|
||
|
even available on disk. Instead, the stream is good until it goes out of scope.
|
||
|
|
||
|
### IBinaryContentConvertable
|
||
|
|
||
|
There is an additional interface that allows a content to be converted into
|
||
|
an `IBinaryContent).`
|
||
|
|
||
|
```c#
|
||
|
FileTextContent textContent;
|
||
|
IBinaryContent binaryContent = textContent.ToBinaryContent();
|
||
|
```
|
||
|
|
||
|
### Extension Methods
|
||
|
|
||
|
There are some convenience methods for working with entity components and
|
||
|
content since they are frequently used.
|
||
|
|
||
|
```c#
|
||
|
IBinaryContent content = entity.GetBinaryContent();
|
||
|
bool has = entity.HasBinaryContent();
|
||
|
|
||
|
// Internally, this uses `SetContent` above with some additonal type safety.
|
||
|
entity = entity.SetBinaryContent(content);
|
||
|
```
|
||
|
|
||
|
### ByteArrayBinaryComponent
|
||
|
|
||
|
The `ByteArrayBinaryComponent` is a component that contains the entire binary
|
||
|
data in memory and returns it via `System.IO.MemoryStream` objects.
|
||
|
|
||
|
```c#
|
||
|
byte[] bytes;
|
||
|
var content = new ByteArrayBinaryComponent(bytes);
|
||
|
```
|
||
|
|
||
|
### FileBinaryContent
|
||
|
|
||
|
The `TextBinaryContent` takes a path or FileInfo object as the parameter and
|
||
|
will produce a stream directly from the file without loading the file into
|
||
|
memory.
|
||
|
|
||
|
```c#
|
||
|
FileInfo file;
|
||
|
|
||
|
new FileBinaryContent(@"C:\Temp\Bob.txt");
|
||
|
new FileBinaryContent(file);
|
||
|
```
|
||
|
|
||
|
## ITextContent
|
||
|
|
||
|
Text content allows for retrieving the contents via `TextReader` instead of a
|
||
|
stream.
|
||
|
|
||
|
```c#
|
||
|
ITextContent content;
|
||
|
|
||
|
using TextReader reader = content.GetReader();
|
||
|
```
|
||
|
|
||
|
### ITextContentConvertable
|
||
|
|
||
|
There is an additional interface that allows a content to be converted into
|
||
|
an `ITextContent).`
|
||
|
|
||
|
```c#
|
||
|
FileBinaryContent binaryContent;
|
||
|
ITextContent textContent = binaryContent.ToTextContent();
|
||
|
```
|
||
|
|
||
|
### Extension Methods
|
||
|
|
||
|
Like the binary, there are some convenience methods for working with entity
|
||
|
components.
|
||
|
|
||
|
```c#
|
||
|
ITextContent content = entity.GetTextContent();
|
||
|
bool has = entity.HasTextContent();
|
||
|
|
||
|
entity = entity.SetTextContent(content);
|
||
|
```
|
||
|
|
||
|
### StringTextContent
|
||
|
|
||
|
A simple, in-memory string text content takes a string as the parameter.
|
||
|
|
||
|
```c#
|
||
|
string input;
|
||
|
ITextContent content = new StringTextContent(input);
|
||
|
```
|
||
|
|
||
|
### FileTextContent
|
||
|
|
||
|
The `TextFileContent` takes a path or FileInfo object as the parameter and will
|
||
|
produce a reader directly from the file without loading the file into memory.
|
||
|
|
||
|
```c#
|
||
|
FileInfo file;
|
||
|
|
||
|
new FileTextContent(@"C:\Temp\Bob.txt");
|
||
|
new FileTextContent(file);
|
||
|
```
|