Skip to content

Commit

Permalink
refactor ContentReader (#1556)
Browse files Browse the repository at this point in the history
* inline InitializeTypeReaders()

* local sharedResourceCount

* rename typeReaderCount

* move typeReaderCount

* rename fields

* refactor readAssetT

* generic ReadAssetT

* base.Read7BitEncodedInt()

* refactor LoadAssetReaders()

* move _contentReadersCache

* simplify _contentReadersCache check

* rename generic ContentReaders fields

* move TypeVersion check

* _isRunningOnNetCore check
  • Loading branch information
nkast authored May 12, 2024
1 parent dc5737b commit d28b1eb
Show file tree
Hide file tree
Showing 9 changed files with 115 additions and 111 deletions.
13 changes: 6 additions & 7 deletions src/Xna.Framework.Content/Content/ContentManager.cs
Original file line number Diff line number Diff line change
Expand Up @@ -200,22 +200,21 @@ protected T ReadAsset<T>(string assetName, Action<IDisposable> recordDisposableO
throw new ObjectDisposedException("ContentManager");

string originalAssetName = assetName;
object result = null;

// Try to load as XNB file
Stream stream = OpenStream(assetName);
using (BinaryReader xnbReader = new BinaryReader(stream))
{
using (ContentReader reader = GetContentReaderFromXnb(assetName, stream, xnbReader, recordDisposableObject))
{
result = reader.ReadAsset<T>();
T result = reader.ReadAsset<T>();

if (result == null)
throw new ContentLoadException("Could not load " + originalAssetName + " asset!");

return result;
}
}

if (result == null)
throw new ContentLoadException("Could not load " + originalAssetName + " asset!");

return (T)result;
}

private ContentReader GetContentReaderFromXnb(string originalAssetName, Stream stream, BinaryReader xnbReader, Action<IDisposable> recordDisposableObject)
Expand Down
83 changes: 39 additions & 44 deletions src/Xna.Framework.Content/Content/ContentReader.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,84 +11,79 @@ namespace Microsoft.Xna.Framework.Content
{
public sealed class ContentReader : BinaryReader
{
private ContentManager contentManager;
private Action<IDisposable> recordDisposableObject;
private ContentManager _contentManager;
private Action<IDisposable> _recordDisposableObject;

private ContentTypeReaderManager typeReaderManager;
private string assetName;
private List<KeyValuePair<int, Action<object>>> sharedResourceFixups;
private ContentTypeReader[] typeReaders;
internal int version;
internal int xnbLength;
internal int sharedResourceCount;
private ContentTypeReaderManager _typeReaderManager;
private string _assetName;
private List<KeyValuePair<int, Action<object>>> _sharedResourceFixups;
private ContentTypeReader[] _typeReaders;
internal int _version;
internal int _xnbLength;

internal ContentTypeReader[] TypeReaders
{
get { return typeReaders; }
get { return _typeReaders; }
}

internal ContentReader(ContentManager manager, Stream stream, string assetName, int version, int xnbLength, Action<IDisposable> recordDisposableObject)
: base(stream)
{
this.recordDisposableObject = recordDisposableObject;
this.contentManager = manager;
this.assetName = assetName;
this.version = version;
this.xnbLength = xnbLength;
this._recordDisposableObject = recordDisposableObject;
this._contentManager = manager;
this._assetName = assetName;
this._version = version;
this._xnbLength = xnbLength;
}

public ContentManager ContentManager
{
get { return contentManager; }
get { return _contentManager; }
}

public string AssetName
{
get { return assetName; }
get { return _assetName; }
}

public ContentBufferPool BufferPool
{
get { return ContentBufferPool.Current; }
}

internal object ReadAsset<T>()
internal T ReadAsset<T>()
{
InitializeTypeReaders();
int typeReaderCount = base.Read7BitEncodedInt();
_typeReaderManager = new ContentTypeReaderManager();
_typeReaders = _typeReaderManager.LoadAssetReaders(this, typeReaderCount);

int sharedResourceCount = base.Read7BitEncodedInt();
_sharedResourceFixups = new List<KeyValuePair<int, Action<object>>>();

// Read primary object
T result = ReadObject<T>();

// Read shared resources
ReadSharedResources();
if (sharedResourceCount > 0)
ReadSharedResources(sharedResourceCount);

return result;
}

internal void InitializeTypeReaders()
{
typeReaderManager = new ContentTypeReaderManager();
typeReaders = typeReaderManager.LoadAssetReaders(this);
sharedResourceCount = Read7BitEncodedInt();
sharedResourceFixups = new List<KeyValuePair<int, Action<object>>>();
}

internal void ReadSharedResources()
internal void ReadSharedResources(int sharedResourceCount)
{
if (sharedResourceCount <= 0)
return;

object[] sharedResources = new object[sharedResourceCount];

for (int i = 0; i < sharedResourceCount; ++i)
{
object existingInstance = null;
sharedResources[i] = ReadObject<object>(existingInstance);
}

// Fixup shared resources by calling each registered action
for (int i = 0; i < sharedResourceFixups.Count; ++i)
for (int i = 0; i < _sharedResourceFixups.Count; ++i)
{
KeyValuePair<int, Action<object>> fixup = sharedResourceFixups[i];
KeyValuePair<int, Action<object>> fixup = _sharedResourceFixups[i];
object sharedResource = sharedResources[fixup.Key];
Action<object> fixupAction = fixup.Value;
fixupAction(sharedResource);
Expand All @@ -101,7 +96,7 @@ public T ReadExternalReference<T>()

if (!String.IsNullOrEmpty(externalReference))
{
return contentManager.Load<T>(FileHelpers.ResolveRelativePath(assetName, externalReference));
return _contentManager.Load<T>(FileHelpers.ResolveRelativePath(_assetName, externalReference));
}

return default(T);
Expand All @@ -113,10 +108,10 @@ private void RecordDisposable<T>(T result)
IDisposable disposable = result as IDisposable;
if (disposable != null)
{
if (recordDisposableObject != null)
recordDisposableObject(disposable);
if (_recordDisposableObject != null)
_recordDisposableObject(disposable);
else
contentManager.RecordDisposable(disposable);
_contentManager.RecordDisposable(disposable);
}
}

Expand All @@ -134,14 +129,14 @@ public T ReadObject<T>(ContentTypeReader typeReader)

public T ReadObject<T>(T existingInstance)
{
int typeReaderIndex = Read7BitEncodedInt();
int typeReaderIndex = base.Read7BitEncodedInt();
if (typeReaderIndex == 0)
return existingInstance;

if (typeReaderIndex > typeReaders.Length)
if (typeReaderIndex > _typeReaders.Length)
throw new ContentLoadException("Incorrect type reader index found!");

ContentTypeReader typeReader = typeReaders[typeReaderIndex - 1];
ContentTypeReader typeReader = _typeReaders[typeReaderIndex - 1];
T result = (T)typeReader.Read(this, existingInstance);

RecordDisposable(result);
Expand Down Expand Up @@ -175,7 +170,7 @@ public T ReadRawObject<T>(ContentTypeReader typeReader)
public T ReadRawObject<T>(T existingInstance)
{
Type objectType = typeof(T);
foreach(ContentTypeReader typeReader in typeReaders)
foreach(ContentTypeReader typeReader in _typeReaders)
{
if(typeReader.TargetType == objectType)
return (T)ReadRawObject<T>(typeReader,existingInstance);
Expand All @@ -190,10 +185,10 @@ public T ReadRawObject<T>(ContentTypeReader typeReader, T existingInstance)

public void ReadSharedResource<T>(Action<T> fixup)
{
int index = Read7BitEncodedInt();
int index = base.Read7BitEncodedInt();
if (index > 0)
{
sharedResourceFixups.Add(new KeyValuePair<int, Action<object>>(index - 1, delegate(object v)
_sharedResourceFixups.Add(new KeyValuePair<int, Action<object>>(index - 1, delegate(object v)
{
if (!(v is T))
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ namespace Microsoft.Xna.Framework.Content
{
internal class ArrayReader<T> : ContentTypeReader<T[]>
{
ContentTypeReader elementReader;
ContentTypeReader _elementReader;

protected internal override void Initialize(ContentTypeReaderManager manager)
{
Type readerType = typeof(T);
elementReader = manager.GetTypeReader(readerType);
_elementReader = manager.GetTypeReader(readerType);
}

protected internal override T[] Read(ContentReader input, T[] existingInstance)
Expand All @@ -28,7 +28,7 @@ protected internal override T[] Read(ContentReader input, T[] existingInstance)
{
for (uint i = 0; i < count; i++)
{
array[i] = input.ReadObject<T>(elementReader);
array[i] = input.ReadObject<T>(_elementReader);
}
}
else
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -11,19 +11,19 @@ namespace Microsoft.Xna.Framework.Content

internal class DictionaryReader<TKey, TValue> : ContentTypeReader<Dictionary<TKey, TValue>>
{
ContentTypeReader keyReader;
ContentTypeReader valueReader;
ContentTypeReader _keyReader;
ContentTypeReader _valueReader;

Type keyType;
Type valueType;
Type _keyType;
Type _valueType;

protected internal override void Initialize(ContentTypeReaderManager manager)
{
keyType = typeof(TKey);
valueType = typeof(TValue);
_keyType = typeof(TKey);
_valueType = typeof(TValue);

keyReader = manager.GetTypeReader(keyType);
valueReader = manager.GetTypeReader(valueType);
_keyReader = manager.GetTypeReader(_keyType);
_valueReader = manager.GetTypeReader(_valueType);
}

public override bool CanDeserializeIntoExistingObject
Expand All @@ -41,16 +41,16 @@ protected internal override Dictionary<TKey, TValue> Read(ContentReader input, D
else
dictionary.Clear();

if (ReflectionHelpers.IsValueType(keyType))
if (ReflectionHelpers.IsValueType(_keyType))
{
for (int i = 0; i < count; i++)
{
TKey key = input.ReadObject<TKey>(keyReader);
TKey key = input.ReadObject<TKey>(_keyReader);

TValue value;
if (ReflectionHelpers.IsValueType(valueType))
if (ReflectionHelpers.IsValueType(_valueType))
{
value = input.ReadObject<TValue>(valueReader);
value = input.ReadObject<TValue>(_valueReader);
}
else
{
Expand All @@ -73,9 +73,9 @@ protected internal override Dictionary<TKey, TValue> Read(ContentReader input, D
: default(TKey);

TValue value;
if (ReflectionHelpers.IsValueType(valueType))
if (ReflectionHelpers.IsValueType(_valueType))
{
value = input.ReadObject<TValue>(valueReader);
value = input.ReadObject<TValue>(_valueReader);
}
else
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,17 +8,17 @@ namespace Microsoft.Xna.Framework.Content
{
internal class EnumReader<T> : ContentTypeReader<T>
{
ContentTypeReader elementReader;
ContentTypeReader _elementReader;

protected internal override void Initialize(ContentTypeReaderManager manager)
{
Type readerType = Enum.GetUnderlyingType(typeof(T));
elementReader = manager.GetTypeReader(readerType);
_elementReader = manager.GetTypeReader(readerType);
}

protected internal override T Read(ContentReader input, T existingInstance)
{
return input.ReadRawObject<T>(elementReader);
return input.ReadRawObject<T>(_elementReader);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,12 +10,12 @@ namespace Microsoft.Xna.Framework.Content
{
internal class ListReader<T> : ContentTypeReader<List<T>>
{
ContentTypeReader elementReader;
ContentTypeReader _elementReader;

protected internal override void Initialize(ContentTypeReaderManager manager)
{
Type readerType = typeof(T);
elementReader = manager.GetTypeReader(readerType);
_elementReader = manager.GetTypeReader(readerType);
}

public override bool CanDeserializeIntoExistingObject
Expand All @@ -33,7 +33,7 @@ protected internal override List<T> Read(ContentReader input, List<T> existingIn
{
for (int i = 0; i < count; i++)
{
list.Add(input.ReadObject<T>(elementReader));
list.Add(input.ReadObject<T>(_elementReader));
}
}
else
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ namespace Microsoft.Xna.Framework.Content
{
internal class MultiArrayReader<T> : ContentTypeReader<Array>
{
ContentTypeReader elementReader;
ContentTypeReader _elementReader;

protected internal override void Initialize(ContentTypeReaderManager manager)
{
Type readerType = typeof(T);
elementReader = manager.GetTypeReader(readerType);
_elementReader = manager.GetTypeReader(readerType);
}

protected internal override Array Read(ContentReader input, Array existingInstance)
Expand All @@ -41,7 +41,7 @@ protected internal override Array Read(ContentReader input, Array existingInstan
{
T value;
if (ReflectionHelpers.IsValueType(typeof(T)))
value = input.ReadObject<T>(elementReader);
value = input.ReadObject<T>(_elementReader);
else
{
int readerType = input.Read7BitEncodedInt();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,18 +8,18 @@ namespace Microsoft.Xna.Framework.Content
{
internal class NullableReader<T> : ContentTypeReader<T?> where T : struct
{
ContentTypeReader elementReader;
ContentTypeReader _elementReader;

protected internal override void Initialize(ContentTypeReaderManager manager)
{
Type readerType = typeof(T);
elementReader = manager.GetTypeReader(readerType);
_elementReader = manager.GetTypeReader(readerType);
}

protected internal override T? Read(ContentReader input, T? existingInstance)
{
if(input.ReadBoolean())
return input.ReadObject<T>(elementReader);
return input.ReadObject<T>(_elementReader);

return null;
}
Expand Down
Loading

0 comments on commit d28b1eb

Please sign in to comment.