# 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()); Assert.True(entity.HasBinaryContent()); Assert.True(entity.HasContent()); entity.SetContent(textContent); Assert.Equal(1, entity.Count); Assert.False(entity.Has()); Assert.False(entity.HasBinaryContent()); Assert.True(entity.Has()); Assert.True(entity.HasTextContent()); Assert.True(entity.HasContent()); entity.RemoveContent(); Assert.Equal(0, entity.Count); Assert.False(entity.Has()); Assert.False(entity.HasBinaryContent()); Assert.False(entity.Has()); 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(); using Stream binaryStream = binaryContent.GetStream(); using StreamReader binaryReader = new StreamReader(binaryStream); var text = binaryReader.ReadToEnd(); var textContent = new StringTextContent(text); var switchedEntity = entity .Set(textContent) .Remove(); Assert.Equal(1, switchedEntity.Count); Assert.True(switchedEntity.Has()); Assert.False(switchedEntity.Has()); var mergedEntity = entity .Set(textContent); Assert.Equal(2, switchedEntity.Count); Assert.True(switchedEntity.Has()); Assert.True(switchedEntity.Has()); ``` 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(); 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); ```