|
@@ -1,6 +1,7 @@
|
|
|
|
|
|
namespace Yuuna.Common.Configuration
|
|
namespace Yuuna.Common.Configuration
|
|
{
|
|
{
|
|
|
|
+ using Microsoft.CodeAnalysis.CSharp;
|
|
using Newtonsoft.Json;
|
|
using Newtonsoft.Json;
|
|
using Newtonsoft.Json.Linq;
|
|
using Newtonsoft.Json.Linq;
|
|
using System;
|
|
using System;
|
|
@@ -8,13 +9,10 @@ namespace Yuuna.Common.Configuration
|
|
using System.ComponentModel;
|
|
using System.ComponentModel;
|
|
using System.Dynamic;
|
|
using System.Dynamic;
|
|
using System.IO;
|
|
using System.IO;
|
|
|
|
+ using System.Linq.Expressions;
|
|
using System.Reflection;
|
|
using System.Reflection;
|
|
- using System.Security.Cryptography;
|
|
|
|
- using System.Text;
|
|
|
|
- using Yuuna.Common.Serialization;
|
|
|
|
-
|
|
|
|
|
|
|
|
- public sealed class ConfigData<T> : DynamicObject, INotifyPropertyChanged
|
|
|
|
|
|
+ public sealed class ConfigProxy : DynamicObject, INotifyPropertyChanged
|
|
{
|
|
{
|
|
public override IEnumerable<string> GetDynamicMemberNames()
|
|
public override IEnumerable<string> GetDynamicMemberNames()
|
|
{
|
|
{
|
|
@@ -53,7 +51,7 @@ namespace Yuuna.Common.Configuration
|
|
|
|
|
|
private static string GetName(Type type)
|
|
private static string GetName(Type type)
|
|
{
|
|
{
|
|
- return type.Name + ".meta";
|
|
|
|
|
|
+ return type.GUID + ".meta";
|
|
}
|
|
}
|
|
|
|
|
|
private readonly FileInfo _meta;
|
|
private readonly FileInfo _meta;
|
|
@@ -89,23 +87,32 @@ namespace Yuuna.Common.Configuration
|
|
writer.Write(json);
|
|
writer.Write(json);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
-
|
|
|
|
- public ConfigData(T graph)
|
|
|
|
|
|
+
|
|
|
|
+ private readonly object _graph;
|
|
|
|
+
|
|
|
|
+ public ConfigProxy(object graph)
|
|
{
|
|
{
|
|
var type = graph?.GetType() ?? throw new ArgumentNullException(nameof(graph));
|
|
var type = graph?.GetType() ?? throw new ArgumentNullException(nameof(graph));
|
|
this._list = new Dictionary<string, Accessor>();
|
|
this._list = new Dictionary<string, Accessor>();
|
|
this._meta = new FileInfo(GetName(type));
|
|
this._meta = new FileInfo(GetName(type));
|
|
|
|
+
|
|
|
|
|
|
-
|
|
|
|
- foreach (var pinfo in type.GetProperties((BindingFlags)52))
|
|
|
|
- if (pinfo.GetCustomAttribute<FieldAttribute>() != null &&
|
|
|
|
-
|
|
|
|
|
|
+ foreach (var pinfo in type.GetProperties((BindingFlags)52))
|
|
|
|
+ if (pinfo.GetCustomAttribute<FieldAttribute>() is FieldAttribute f &&
|
|
pinfo.GetGetMethod(true) is MethodInfo getter &&
|
|
pinfo.GetGetMethod(true) is MethodInfo getter &&
|
|
pinfo.GetSetMethod(true) is MethodInfo setter)
|
|
pinfo.GetSetMethod(true) is MethodInfo setter)
|
|
{
|
|
{
|
|
var getDele = Delegate.CreateDelegate(typeof(Func<>).MakeGenericType(getter.ReturnType), graph, getter);
|
|
var getDele = Delegate.CreateDelegate(typeof(Func<>).MakeGenericType(getter.ReturnType), graph, getter);
|
|
var setDele = Delegate.CreateDelegate(typeof(Action<>).MakeGenericType(setter.GetParameters()[0].ParameterType), graph, setter);
|
|
var setDele = Delegate.CreateDelegate(typeof(Action<>).MakeGenericType(setter.GetParameters()[0].ParameterType), graph, setter);
|
|
- this._list.Add(pinfo.Name, new Accessor(pinfo.PropertyType , getDele, setDele));
|
|
|
|
|
|
+
|
|
|
|
+
|
|
|
|
+ var identifier =
|
|
|
|
+ f.Alias is string alias
|
|
|
|
+ ? SyntaxFacts.IsValidIdentifier(alias)
|
|
|
|
+ ? alias
|
|
|
|
+ : throw new ArgumentException("Invalid member name", alias)
|
|
|
|
+ : pinfo.Name;
|
|
|
|
+ this._list.Add(identifier, new Accessor(pinfo.PropertyType , getDele, setDele));
|
|
}
|
|
}
|
|
|
|
|
|
// metadata not found, create and serialize object to file.
|
|
// metadata not found, create and serialize object to file.
|
|
@@ -115,8 +122,7 @@ namespace Yuuna.Common.Configuration
|
|
}
|
|
}
|
|
|
|
|
|
this.Load();
|
|
this.Load();
|
|
-
|
|
|
|
-
|
|
|
|
|
|
+ this._graph = graph;
|
|
}
|
|
}
|
|
|
|
|
|
private struct Accessor
|
|
private struct Accessor
|
|
@@ -180,23 +186,14 @@ namespace Yuuna.Common.Configuration
|
|
}
|
|
}
|
|
throw new ArgumentOutOfRangeException();
|
|
throw new ArgumentOutOfRangeException();
|
|
}
|
|
}
|
|
- }
|
|
|
|
|
|
+
|
|
|
|
+ public override bool Equals(object obj) => this._graph.Equals(obj);
|
|
|
|
+
|
|
|
|
+ public override int GetHashCode() => this._graph.GetHashCode();
|
|
|
|
|
|
- public static class ConfigExtension
|
|
|
|
- {
|
|
|
|
- public static dynamic Bind<T>(this T obj, PropertyChangedEventHandler onPropertyChnaged = null, bool autoSave = true)
|
|
|
|
- {
|
|
|
|
- var p = new ConfigData<T>(obj);
|
|
|
|
- if (onPropertyChnaged != null)
|
|
|
|
- p.PropertyChanged += onPropertyChnaged;
|
|
|
|
- if (autoSave)
|
|
|
|
- p.PropertyChanged += delegate { p.Save(); };
|
|
|
|
- return p;
|
|
|
|
- }
|
|
|
|
- }
|
|
|
|
|
|
+ public override string ToString() => this._graph.ToString();
|
|
|
|
|
|
- [AttributeUsage(AttributeTargets.Property)]
|
|
|
|
- public sealed class FieldAttribute : Attribute
|
|
|
|
- {
|
|
|
|
|
|
+ public new Type GetType() => this._graph.GetType();
|
|
|
|
+
|
|
}
|
|
}
|
|
}
|
|
}
|