Browse Source

Added some Net3 support stuff and implemented IConfigStore in GeneratedStore

pull/46/head
Anairkoen Schno 5 years ago
parent
commit
0131c2b94b
3 changed files with 125 additions and 16 deletions
  1. +105
    -16
      IPA.Loader/Config/Stores/GeneratedStore.cs
  2. +19
    -0
      Net3-Proxy/Array.cs
  3. +1
    -0
      Net3-Proxy/Net3-Proxy.csproj

+ 105
- 16
IPA.Loader/Config/Stores/GeneratedStore.cs View File

@ -8,6 +8,10 @@ using System.Reflection.Emit;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
#if NET3
using Net3_Proxy;
using Array = Net3_Proxy.Array;
#endif
namespace IPA.Config.Stores namespace IPA.Config.Stores
{ {
@ -33,8 +37,10 @@ namespace IPA.Config.Stores
private readonly AutoResetEvent resetEvent = new AutoResetEvent(false); private readonly AutoResetEvent resetEvent = new AutoResetEvent(false);
public WaitHandle SyncObject => resetEvent; public WaitHandle SyncObject => resetEvent;
internal static MethodInfo SyncObjectGetMethod = typeof(Impl).GetProperty(nameof(SyncObject)).GetGetMethod();
public ReaderWriterLockSlim WriteSyncObject { get; } = new ReaderWriterLockSlim(); public ReaderWriterLockSlim WriteSyncObject { get; } = new ReaderWriterLockSlim();
internal static MethodInfo WriteSyncObjectGetMethod = typeof(Impl).GetProperty(nameof(WriteSyncObject)).GetGetMethod();
internal static MethodInfo ImplSignalChangedMethod = typeof(Impl).GetMethod(nameof(ImplSignalChanged)); internal static MethodInfo ImplSignalChangedMethod = typeof(Impl).GetMethod(nameof(ImplSignalChanged));
internal static void ImplSignalChanged(IGeneratedStore s) => FindImpl(s).SignalChanged(); internal static void ImplSignalChanged(IGeneratedStore s) => FindImpl(s).SignalChanged();
@ -149,7 +155,7 @@ namespace IPA.Config.Stores
var GetTypeFromHandle = typeof(Type).GetMethod(nameof(Type.GetTypeFromHandle)); var GetTypeFromHandle = typeof(Type).GetMethod(nameof(Type.GetTypeFromHandle));
#region Parse base object structure
#region Parse base object structure
var baseChanged = type.GetMethod("Changed", BindingFlags.Public | BindingFlags.Instance, null, Type.EmptyTypes, Array.Empty<ParameterModifier>()); var baseChanged = type.GetMethod("Changed", BindingFlags.Public | BindingFlags.Instance, null, Type.EmptyTypes, Array.Empty<ParameterModifier>());
if (baseChanged != null && !baseChanged.IsVirtual) baseChanged = null; // limit this to just the one thing if (baseChanged != null && !baseChanged.IsVirtual) baseChanged = null; // limit this to just the one thing
@ -185,9 +191,9 @@ namespace IPA.Config.Stores
structure.Add(smi.Name, smi); structure.Add(smi.Name, smi);
} }
#endregion
#endregion
#region Constructor
#region Constructor
// takes its parent // takes its parent
var ctor = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, new[] { typeof(IGeneratedStore) }); var ctor = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, new[] { typeof(IGeneratedStore) });
{ {
@ -219,12 +225,13 @@ namespace IPA.Config.Stores
il.Emit(OpCodes.Ret); il.Emit(OpCodes.Ret);
} }
#endregion
#endregion
const MethodAttributes propertyMethodAttr = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig; const MethodAttributes propertyMethodAttr = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig;
const MethodAttributes virtualPropertyMethodAttr = propertyMethodAttr | MethodAttributes.Virtual | MethodAttributes.Final; const MethodAttributes virtualPropertyMethodAttr = propertyMethodAttr | MethodAttributes.Virtual | MethodAttributes.Final;
const MethodAttributes virtualMemberMethod = MethodAttributes.Public | MethodAttributes.Virtual | MethodAttributes.HideBySig | MethodAttributes.Final;
#region IGeneratedStore
#region IGeneratedStore
typeBuilder.AddInterfaceImplementation(typeof(IGeneratedStore)); typeBuilder.AddInterfaceImplementation(typeof(IGeneratedStore));
var IGeneratedStore_t = typeof(IGeneratedStore); var IGeneratedStore_t = typeof(IGeneratedStore);
@ -234,7 +241,7 @@ namespace IPA.Config.Stores
var IGeneratedStore_GetValues = IGeneratedStore_t.GetProperty(nameof(IGeneratedStore.Values)).GetGetMethod(); var IGeneratedStore_GetValues = IGeneratedStore_t.GetProperty(nameof(IGeneratedStore.Values)).GetGetMethod();
var IGeneratedStore_SetValues = IGeneratedStore_t.GetProperty(nameof(IGeneratedStore.Values)).GetSetMethod(); var IGeneratedStore_SetValues = IGeneratedStore_t.GetProperty(nameof(IGeneratedStore.Values)).GetSetMethod();
#region IGeneratedStore.Impl
#region IGeneratedStore.Impl
var implProp = typeBuilder.DefineProperty(nameof(IGeneratedStore.Impl), PropertyAttributes.None, typeof(Impl), null); var implProp = typeBuilder.DefineProperty(nameof(IGeneratedStore.Impl), PropertyAttributes.None, typeof(Impl), null);
var implPropGet = typeBuilder.DefineMethod($"<g>{nameof(IGeneratedStore.Impl)}", virtualPropertyMethodAttr, implProp.PropertyType, Type.EmptyTypes); var implPropGet = typeBuilder.DefineMethod($"<g>{nameof(IGeneratedStore.Impl)}", virtualPropertyMethodAttr, implProp.PropertyType, Type.EmptyTypes);
implProp.SetGetMethod(implPropGet); implProp.SetGetMethod(implPropGet);
@ -247,8 +254,8 @@ namespace IPA.Config.Stores
il.Emit(OpCodes.Ldfld, implField); // load impl field il.Emit(OpCodes.Ldfld, implField); // load impl field
il.Emit(OpCodes.Ret); il.Emit(OpCodes.Ret);
} }
#endregion
#region IGeneratedStore.Type
#endregion
#region IGeneratedStore.Type
var typeProp = typeBuilder.DefineProperty(nameof(IGeneratedStore.Type), PropertyAttributes.None, typeof(Type), null); var typeProp = typeBuilder.DefineProperty(nameof(IGeneratedStore.Type), PropertyAttributes.None, typeof(Type), null);
var typePropGet = typeBuilder.DefineMethod($"<g>{nameof(IGeneratedStore.Type)}", virtualPropertyMethodAttr, typeProp.PropertyType, Type.EmptyTypes); var typePropGet = typeBuilder.DefineMethod($"<g>{nameof(IGeneratedStore.Type)}", virtualPropertyMethodAttr, typeProp.PropertyType, Type.EmptyTypes);
typeProp.SetGetMethod(typePropGet); typeProp.SetGetMethod(typePropGet);
@ -261,8 +268,8 @@ namespace IPA.Config.Stores
il.Emit(OpCodes.Ldfld, typeField); // load impl field il.Emit(OpCodes.Ldfld, typeField); // load impl field
il.Emit(OpCodes.Ret); il.Emit(OpCodes.Ret);
} }
#endregion
#region IGeneratedStore.Parent
#endregion
#region IGeneratedStore.Parent
var parentProp = typeBuilder.DefineProperty(nameof(IGeneratedStore.Parent), PropertyAttributes.None, typeof(IGeneratedStore), null); var parentProp = typeBuilder.DefineProperty(nameof(IGeneratedStore.Parent), PropertyAttributes.None, typeof(IGeneratedStore), null);
var parentPropGet = typeBuilder.DefineMethod($"<g>{nameof(IGeneratedStore.Parent)}", virtualPropertyMethodAttr, parentProp.PropertyType, Type.EmptyTypes); var parentPropGet = typeBuilder.DefineMethod($"<g>{nameof(IGeneratedStore.Parent)}", virtualPropertyMethodAttr, parentProp.PropertyType, Type.EmptyTypes);
parentProp.SetGetMethod(parentPropGet); parentProp.SetGetMethod(parentPropGet);
@ -275,8 +282,8 @@ namespace IPA.Config.Stores
il.Emit(OpCodes.Ldfld, parentField); // load impl field il.Emit(OpCodes.Ldfld, parentField); // load impl field
il.Emit(OpCodes.Ret); il.Emit(OpCodes.Ret);
} }
#endregion
#region IGeneratedStore.Values
#endregion
#region IGeneratedStore.Values
var valuesProp = typeBuilder.DefineProperty(nameof(IGeneratedStore.Values), PropertyAttributes.None, typeof(Value), null); var valuesProp = typeBuilder.DefineProperty(nameof(IGeneratedStore.Values), PropertyAttributes.None, typeof(Value), null);
var valuesPropGet = typeBuilder.DefineMethod($"<g>{nameof(IGeneratedStore.Values)}", virtualPropertyMethodAttr, valuesProp.PropertyType, Type.EmptyTypes); var valuesPropGet = typeBuilder.DefineMethod($"<g>{nameof(IGeneratedStore.Values)}", virtualPropertyMethodAttr, valuesProp.PropertyType, Type.EmptyTypes);
var valuesPropSet = typeBuilder.DefineMethod($"<s>{nameof(IGeneratedStore.Values)}", virtualPropertyMethodAttr, null, new[] { valuesProp.PropertyType }); var valuesPropSet = typeBuilder.DefineMethod($"<s>{nameof(IGeneratedStore.Values)}", virtualPropertyMethodAttr, null, new[] { valuesProp.PropertyType });
@ -301,10 +308,83 @@ namespace IPA.Config.Stores
il.Emit(OpCodes.Ret); il.Emit(OpCodes.Ret);
} }
#endregion
#endregion
#endregion
#endregion
#region Changed
#region IConfigStore
typeBuilder.AddInterfaceImplementation(typeof(IConfigStore));
var IConfigStore_t = typeof(IConfigStore);
var IConfigStore_GetSyncObject = IConfigStore_t.GetProperty(nameof(IConfigStore.SyncObject)).GetGetMethod();
var IConfigStore_GetWriteSyncObject = IConfigStore_t.GetProperty(nameof(IConfigStore.WriteSyncObject)).GetGetMethod();
var IConfigStore_WriteTo = IConfigStore_t.GetMethod(nameof(IConfigStore.WriteTo));
var IConfigStore_ReadFrom = IConfigStore_t.GetMethod(nameof(IConfigStore.ReadFrom));
#region IConfigStore.SyncObject
var syncObjProp = typeBuilder.DefineProperty(nameof(IConfigStore.SyncObject), PropertyAttributes.None, typeof(WaitHandle), null);
var syncObjPropGet = typeBuilder.DefineMethod($"<g>{nameof(IConfigStore.SyncObject)}", virtualPropertyMethodAttr, syncObjProp.PropertyType, Type.EmptyTypes);
syncObjProp.SetGetMethod(syncObjPropGet);
typeBuilder.DefineMethodOverride(syncObjPropGet, IConfigStore_GetSyncObject);
{
var il = syncObjPropGet.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Call, Impl.FindImplMethod);
il.Emit(OpCodes.Tailcall);
il.Emit(OpCodes.Call, Impl.SyncObjectGetMethod);
il.Emit(OpCodes.Ret);
}
#endregion
#region IConfigStore.WriteSyncObject
var writeSyncObjProp = typeBuilder.DefineProperty(nameof(IConfigStore.WriteSyncObject), PropertyAttributes.None, typeof(WaitHandle), null);
var writeSyncObjPropGet = typeBuilder.DefineMethod($"<g>{nameof(IConfigStore.WriteSyncObject)}", virtualPropertyMethodAttr, writeSyncObjProp.PropertyType, Type.EmptyTypes);
writeSyncObjProp.SetGetMethod(writeSyncObjPropGet);
typeBuilder.DefineMethodOverride(writeSyncObjPropGet, IConfigStore_GetWriteSyncObject);
{
var il = writeSyncObjPropGet.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Call, Impl.FindImplMethod);
il.Emit(OpCodes.Tailcall);
il.Emit(OpCodes.Call, Impl.WriteSyncObjectGetMethod);
il.Emit(OpCodes.Ret);
}
#endregion
#region IConfigStore.WriteTo
var writeTo = typeBuilder.DefineMethod($"<>{nameof(IConfigStore.WriteTo)}", virtualMemberMethod, null, new[] { typeof(IConfigProvider) });
typeBuilder.DefineMethodOverride(writeTo, IConfigStore_WriteTo);
{
var il = writeTo.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Call, Impl.FindImplMethod);
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Tailcall);
il.Emit(OpCodes.Call, Impl.WriteToMethod);
il.Emit(OpCodes.Ret);
}
#endregion
#region IConfigStore.ReadFrom
var readFrom = typeBuilder.DefineMethod($"<>{nameof(IConfigStore.ReadFrom)}", virtualMemberMethod, null, new[] { typeof(IConfigProvider) });
typeBuilder.DefineMethodOverride(readFrom, IConfigStore_ReadFrom);
{
var il = writeTo.GetILGenerator();
il.Emit(OpCodes.Ldarg_0);
il.Emit(OpCodes.Call, Impl.FindImplMethod);
il.Emit(OpCodes.Ldarg_1);
il.Emit(OpCodes.Tailcall);
il.Emit(OpCodes.Call, Impl.ReadFromMethod);
il.Emit(OpCodes.Ret);
}
#endregion
#endregion
#region Changed
var coreChanged = typeBuilder.DefineMethod( var coreChanged = typeBuilder.DefineMethod(
"<>Changed", "<>Changed",
MethodAttributes.Public | MethodAttributes.HideBySig, MethodAttributes.Public | MethodAttributes.HideBySig,
@ -340,10 +420,19 @@ namespace IPA.Config.Stores
coreChanged = changedMethod; // switch to calling this version instead of just the default coreChanged = changedMethod; // switch to calling this version instead of just the default
} }
#endregion
#endregion
// TODO: generate overrides for all the virtual properties // TODO: generate overrides for all the virtual properties
var genType = typeBuilder.CreateType();
{ // register a member map
var dict = new Dictionary<string, Type>();
foreach (var kvp in structure)
dict.Add(kvp.Key, kvp.Value.Type);
memberMaps.Add(type, dict);
}
return null; return null;
} }


+ 19
- 0
Net3-Proxy/Array.cs View File

@ -0,0 +1,19 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using OgArray = System.Array;
namespace Net3_Proxy
{
public static class Array
{
private static class EmptyArray<T>
{
public static readonly T[] Value = new T[0];
}
public static T[] Empty<T>() => EmptyArray<T>.Value;
}
}

+ 1
- 0
Net3-Proxy/Net3-Proxy.csproj View File

@ -39,6 +39,7 @@
<Reference Include="System.Xml" /> <Reference Include="System.Xml" />
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<Compile Include="Array.cs" />
<Compile Include="Directory.cs" /> <Compile Include="Directory.cs" />
<Compile Include="Extensions.cs" /> <Compile Include="Extensions.cs" />
<Compile Include="File.cs" /> <Compile Include="File.cs" />


Loading…
Cancel
Save