attribute individual fields, not the class

This commit is contained in:
Bob
2010-08-27 19:13:42 +12:00
committed by Chris Forbes
parent 29a77f7c5c
commit 9fedeefdbc
6 changed files with 52 additions and 71 deletions

View File

@@ -165,49 +165,30 @@ namespace OpenRA.FileFormats
{ {
var ret = new Dictionary<FieldInfo, Func<string, Type, MiniYaml, object>>(); var ret = new Dictionary<FieldInfo, Func<string, Type, MiniYaml, object>>();
var fieldsToLoad = new List<FieldInfo>();
var attr = (FooAttribute[])type.GetCustomAttributes( typeof( FooAttribute ), false );
if( attr.Length == 0 )
{
var defCtor = type.GetConstructor( new Type[ 0 ] );
if( defCtor == null || ( defCtor.GetMethodImplementationFlags() | MethodImplAttributes.Runtime ) == 0 )
throw new InvalidOperationException( "FieldLoader: refusing to load type {0}; has non-default ctor".F( type ) );
fieldsToLoad.AddRange( type.GetFields() );
}
else if( attr[ 0 ].Fields != null )
fieldsToLoad.AddRange( attr[ 0 ].Fields.Select( x => type.GetField( x ) ) );
else
fieldsToLoad.AddRange( type.GetFields() );
foreach( var field in fieldsToLoad )
ret.Add( field, null );
foreach( var field in type.GetFields() ) foreach( var field in type.GetFields() )
{ {
var use = (LoadUsingAttribute[])field.GetCustomAttributes( typeof( LoadUsingAttribute ), false ); var load = (LoadAttribute[])field.GetCustomAttributes( typeof( LoadAttribute ), false );
if( use.Length != 0 ) var loadUsing = (LoadUsingAttribute[])field.GetCustomAttributes( typeof( LoadUsingAttribute ), false );
ret[ field ] = ( _1, fieldType, yaml ) => use[ 0 ].LoaderFunc( field )( yaml ); var fromYamlKey = (FieldFromYamlKeyAttribute[])field.GetCustomAttributes( typeof( FieldFromYamlKeyAttribute ), false );
else if( loadUsing.Length != 0 )
{ ret[ field ] = ( _1, fieldType, yaml ) => loadUsing[ 0 ].LoaderFunc( field )( yaml );
var attr2 = (FieldFromYamlKeyAttribute[])field.GetCustomAttributes( typeof( FieldFromYamlKeyAttribute ), false ); else if( fromYamlKey.Length != 0 )
if( attr2.Length != 0 ) ret[ field ] = ( f, ft, yaml ) => GetValue( f, ft, yaml.Value );
ret[ field ] = ( f, ft, yaml ) => GetValue( f, ft, yaml.Value ); else if( load.Length != 0 )
} ret[ field ] = null;
} }
if( ret.Count == 0 )
foreach( var f in type.GetFields() )
ret.Add( f, null );
return ret; return ret;
} }
public class FooAttribute : Attribute [AttributeUsage( AttributeTargets.Field )]
{ public class LoadAttribute : Attribute { }
public string[] Fields;
public FooAttribute( params string[] fields )
{
Fields = fields;
}
}
[AttributeUsage( AttributeTargets.Field )]
public class LoadUsingAttribute : Attribute public class LoadUsingAttribute : Attribute
{ {
Func<MiniYaml, object> loaderFuncCache; Func<MiniYaml, object> loaderFuncCache;

View File

@@ -15,27 +15,26 @@ using System.Linq;
namespace OpenRA.FileFormats namespace OpenRA.FileFormats
{ {
[FieldLoader.Foo( "Selectable", "Title", "Description", "Author", "PlayerCount", "Tileset", "TopLeft", "BottomRight" )]
public class MapStub public class MapStub
{ {
public readonly IFolder Package; public readonly IFolder Package;
// Yaml map data // Yaml map data
public readonly string Uid; public readonly string Uid;
public bool Selectable; [FieldLoader.Load] public bool Selectable;
public string Title; [FieldLoader.Load] public string Title;
public string Description; [FieldLoader.Load] public string Description;
public string Author; [FieldLoader.Load] public string Author;
public int PlayerCount; [FieldLoader.Load] public int PlayerCount;
public string Tileset; [FieldLoader.Load] public string Tileset;
[FieldLoader.LoadUsing( "LoadWaypoints" )] [FieldLoader.LoadUsing( "LoadWaypoints" )]
public Dictionary<string, int2> Waypoints = new Dictionary<string, int2>(); public Dictionary<string, int2> Waypoints = new Dictionary<string, int2>();
public IEnumerable<int2> SpawnPoints { get { return Waypoints.Select(kv => kv.Value); } } public IEnumerable<int2> SpawnPoints { get { return Waypoints.Select(kv => kv.Value); } }
public int2 TopLeft; [FieldLoader.Load] public int2 TopLeft;
public int2 BottomRight; [FieldLoader.Load] public int2 BottomRight;
public int Width { get { return BottomRight.X - TopLeft.X; } } public int Width { get { return BottomRight.X - TopLeft.X; } }
public int Height { get { return BottomRight.Y - TopLeft.Y; } } public int Height { get { return BottomRight.Y - TopLeft.Y; } }

View File

@@ -29,13 +29,12 @@ namespace OpenRA.FileFormats
public MiniYaml Save() { return FieldSaver.Save(this); } public MiniYaml Save() { return FieldSaver.Save(this); }
} }
[FieldLoader.Foo("Id", "Image", "Size", "PickAny")]
public class TileTemplate public class TileTemplate
{ {
public ushort Id; [FieldLoader.Load] public ushort Id;
public string Image; [FieldLoader.Load] public string Image;
public int2 Size; [FieldLoader.Load] public int2 Size;
public bool PickAny; [FieldLoader.Load] public bool PickAny;
[FieldLoader.LoadUsing( "LoadTiles" )] [FieldLoader.LoadUsing( "LoadTiles" )]
public Dictionary<byte, string> Tiles = new Dictionary<byte, string>(); public Dictionary<byte, string> Tiles = new Dictionary<byte, string>();
@@ -84,7 +83,7 @@ namespace OpenRA.FileFormats
public TileSet() {} public TileSet() {}
public TileSet( string filepath ) public TileSet( string filepath )
{ {
var yaml = MiniYaml.FromFile(filepath).ToDictionary( x => x.Key, x => x.Value ); var yaml = MiniYaml.DictFromFile( filepath );
// General info // General info
FieldLoader.Load(this, yaml["General"]); FieldLoader.Load(this, yaml["General"]);

View File

@@ -12,12 +12,11 @@ using OpenRA.FileFormats;
namespace OpenRA.GameRules namespace OpenRA.GameRules
{ {
[FieldLoader.Foo()]
public class MusicInfo public class MusicInfo
{ {
public readonly string Filename = null; [FieldLoader.Load] public readonly string Filename = null;
public readonly string Title = null; [FieldLoader.Load] public readonly string Title = null;
public readonly int Length = 0; // seconds [FieldLoader.Load] public readonly int Length = 0; // seconds
public MusicInfo( string key, MiniYaml value ) public MusicInfo( string key, MiniYaml value )
{ {

View File

@@ -15,17 +15,21 @@ using System;
namespace OpenRA.GameRules namespace OpenRA.GameRules
{ {
[FieldLoader.Foo( "DisableVariants" )]
public class VoiceInfo public class VoiceInfo
{ {
public readonly Dictionary<string,string[]> Variants; public readonly Dictionary<string,string[]> Variants;
public readonly Dictionary<string,string[]> Voices; public readonly Dictionary<string,string[]> Voices;
public readonly string DefaultVariant = ".aud" ; public readonly string DefaultVariant = ".aud" ;
public readonly string[] DisableVariants = { }; [FieldLoader.Load] public readonly string[] DisableVariants = { };
Func<MiniYaml, string, Dictionary<string, string[]>> Load = (y,name) => (y.NodesDict.ContainsKey(name))? y.NodesDict[name].NodesDict.ToDictionary(a => a.Key, static Dictionary<string, string[]> Load( MiniYaml y, string name )
a => (string[])FieldLoader.GetValue( "(value)", typeof(string[]), a.Value.Value )) {
: new Dictionary<string, string[]>(); return y.NodesDict.ContainsKey( name )
? y.NodesDict[ name ].NodesDict.ToDictionary(
a => a.Key,
a => (string[])FieldLoader.GetValue( "(value)", typeof( string[] ), a.Value.Value ) )
: new Dictionary<string, string[]>();
}
public readonly Lazy<Dictionary<string, VoicePool>> Pools; public readonly Lazy<Dictionary<string, VoicePool>> Pools;

View File

@@ -19,20 +19,19 @@ using OpenRA.FileFormats;
namespace OpenRA namespace OpenRA
{ {
[FieldLoader.Foo( "Selectable", "MapFormat", "Title", "Description", "Author", "PlayerCount", "Tileset", "MapSize", "TopLeft", "BottomRight" )]
public class Map public class Map
{ {
public IFolder Package; public IFolder Package;
public string Uid; public string Uid;
// Yaml map data // Yaml map data
public bool Selectable = true; [FieldLoader.Load] public bool Selectable = true;
public int MapFormat; [FieldLoader.Load] public int MapFormat;
public string Title; [FieldLoader.Load] public string Title;
public string Description; [FieldLoader.Load] public string Description;
public string Author; [FieldLoader.Load] public string Author;
public int PlayerCount; [FieldLoader.Load] public int PlayerCount;
public string Tileset; [FieldLoader.Load] public string Tileset;
public Dictionary<string, PlayerReference> Players = new Dictionary<string, PlayerReference>(); public Dictionary<string, PlayerReference> Players = new Dictionary<string, PlayerReference>();
public Dictionary<string, ActorReference> Actors = new Dictionary<string, ActorReference>(); public Dictionary<string, ActorReference> Actors = new Dictionary<string, ActorReference>();
@@ -44,10 +43,10 @@ namespace OpenRA
// Binary map data // Binary map data
public byte TileFormat = 1; public byte TileFormat = 1;
public int2 MapSize; [FieldLoader.Load] public int2 MapSize;
public int2 TopLeft; [FieldLoader.Load] public int2 TopLeft;
public int2 BottomRight; [FieldLoader.Load] public int2 BottomRight;
public TileReference<ushort, byte>[,] MapTiles; public TileReference<ushort, byte>[,] MapTiles;
public TileReference<byte, byte>[,] MapResources; public TileReference<byte, byte>[,] MapResources;