Skip to content
This repository was archived by the owner on Dec 24, 2022. It is now read-only.

Commit e872552

Browse files
committed
Restore UseType() and merge DynamicProxy with Pcl.Dynamic
1 parent d48c31f commit e872552

File tree

7 files changed

+172
-170
lines changed

7 files changed

+172
-170
lines changed

src/ServiceStack.Text/DynamicProxy.cs

Lines changed: 0 additions & 165 deletions
This file was deleted.

src/ServiceStack.Text/Pcl.Dynamic.cs

Lines changed: 163 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,11 @@
1212
using System.Linq;
1313
using System.Text;
1414

15+
#if !(SL5 || __IOS__ || NETFX_CORE)
16+
using System.Reflection;
17+
using System.Reflection.Emit;
18+
#endif
19+
1520
namespace ServiceStack
1621
{
1722
public static class DeserializeDynamic<TSerializer>
@@ -183,6 +188,163 @@ internal static string Underscored(IEnumerable<char> pascalCase)
183188
}
184189
}
185190
#endif
186-
}
187191

192+
#if !(SL5 || __IOS__ || NETFX_CORE)
193+
public static class DynamicProxy
194+
{
195+
public static T GetInstanceFor<T>()
196+
{
197+
return (T)GetInstanceFor(typeof(T));
198+
}
199+
200+
static readonly ModuleBuilder ModuleBuilder;
201+
static readonly AssemblyBuilder DynamicAssembly;
202+
static readonly Type[] EmptyTypes = new Type[0];
203+
204+
public static object GetInstanceFor(Type targetType)
205+
{
206+
lock (DynamicAssembly)
207+
{
208+
var constructedType = DynamicAssembly.GetType(ProxyName(targetType)) ?? GetConstructedType(targetType);
209+
var instance = Activator.CreateInstance(constructedType);
210+
return instance;
211+
}
212+
}
213+
214+
static string ProxyName(Type targetType)
215+
{
216+
return targetType.Name + "Proxy";
217+
}
218+
219+
static DynamicProxy()
220+
{
221+
var assemblyName = new AssemblyName("DynImpl");
222+
#if NETSTANDARD1_1
223+
DynamicAssembly = AssemblyBuilder.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
224+
#else
225+
DynamicAssembly = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave);
226+
#endif
227+
ModuleBuilder = DynamicAssembly.DefineDynamicModule("DynImplModule");
228+
}
229+
230+
static Type GetConstructedType(Type targetType)
231+
{
232+
var typeBuilder = ModuleBuilder.DefineType(targetType.Name + "Proxy", TypeAttributes.Public);
233+
234+
var ctorBuilder = typeBuilder.DefineConstructor(
235+
MethodAttributes.Public,
236+
CallingConventions.Standard,
237+
new Type[] { });
238+
var ilGenerator = ctorBuilder.GetILGenerator();
239+
ilGenerator.Emit(OpCodes.Ret);
240+
241+
IncludeType(targetType, typeBuilder);
242+
243+
foreach (var face in targetType.GetTypeInterfaces())
244+
IncludeType(face, typeBuilder);
245+
246+
#if NETSTANDARD1_1
247+
return typeBuilder.CreateTypeInfo().AsType();
248+
#else
249+
return typeBuilder.CreateType();
250+
#endif
251+
}
252+
253+
static void IncludeType(Type typeOfT, TypeBuilder typeBuilder)
254+
{
255+
var methodInfos = typeOfT.GetMethodInfos();
256+
foreach (var methodInfo in methodInfos)
257+
{
258+
if (methodInfo.Name.StartsWith("set_", StringComparison.Ordinal)) continue; // we always add a set for a get.
259+
260+
if (methodInfo.Name.StartsWith("get_", StringComparison.Ordinal))
261+
{
262+
BindProperty(typeBuilder, methodInfo);
263+
}
264+
else
265+
{
266+
BindMethod(typeBuilder, methodInfo);
267+
}
268+
}
269+
270+
typeBuilder.AddInterfaceImplementation(typeOfT);
271+
}
272+
273+
static void BindMethod(TypeBuilder typeBuilder, MethodInfo methodInfo)
274+
{
275+
var methodBuilder = typeBuilder.DefineMethod(
276+
methodInfo.Name,
277+
MethodAttributes.Public | MethodAttributes.Virtual,
278+
methodInfo.ReturnType,
279+
methodInfo.GetParameters().Select(p => p.GetType()).ToArray()
280+
);
281+
var methodILGen = methodBuilder.GetILGenerator();
282+
if (methodInfo.ReturnType == typeof(void))
283+
{
284+
methodILGen.Emit(OpCodes.Ret);
285+
}
286+
else
287+
{
288+
if (methodInfo.ReturnType.IsValueType() || methodInfo.ReturnType.IsEnum())
289+
{
290+
#if NETSTANDARD1_1
291+
MethodInfo getMethod = typeof(Activator).GetMethod("CreateInstance");
292+
#else
293+
MethodInfo getMethod = typeof(Activator).GetMethod("CreateInstance",
294+
new[] { typeof(Type) });
295+
#endif
296+
LocalBuilder lb = methodILGen.DeclareLocal(methodInfo.ReturnType);
297+
methodILGen.Emit(OpCodes.Ldtoken, lb.LocalType);
298+
methodILGen.Emit(OpCodes.Call, typeof(Type).GetMethod("GetTypeFromHandle"));
299+
methodILGen.Emit(OpCodes.Callvirt, getMethod);
300+
methodILGen.Emit(OpCodes.Unbox_Any, lb.LocalType);
301+
}
302+
else
303+
{
304+
methodILGen.Emit(OpCodes.Ldnull);
305+
}
306+
methodILGen.Emit(OpCodes.Ret);
307+
}
308+
typeBuilder.DefineMethodOverride(methodBuilder, methodInfo);
309+
}
310+
311+
public static void BindProperty(TypeBuilder typeBuilder, MethodInfo methodInfo)
312+
{
313+
// Backing Field
314+
string propertyName = methodInfo.Name.Replace("get_", "");
315+
Type propertyType = methodInfo.ReturnType;
316+
FieldBuilder backingField = typeBuilder.DefineField("_" + propertyName, propertyType, FieldAttributes.Private);
317+
318+
//Getter
319+
MethodBuilder backingGet = typeBuilder.DefineMethod("get_" + propertyName, MethodAttributes.Public |
320+
MethodAttributes.SpecialName | MethodAttributes.Virtual |
321+
MethodAttributes.HideBySig, propertyType, EmptyTypes);
322+
ILGenerator getIl = backingGet.GetILGenerator();
323+
324+
getIl.Emit(OpCodes.Ldarg_0);
325+
getIl.Emit(OpCodes.Ldfld, backingField);
326+
getIl.Emit(OpCodes.Ret);
327+
328+
329+
//Setter
330+
MethodBuilder backingSet = typeBuilder.DefineMethod("set_" + propertyName, MethodAttributes.Public |
331+
MethodAttributes.SpecialName | MethodAttributes.Virtual |
332+
MethodAttributes.HideBySig, null, new[] { propertyType });
333+
334+
ILGenerator setIl = backingSet.GetILGenerator();
335+
336+
setIl.Emit(OpCodes.Ldarg_0);
337+
setIl.Emit(OpCodes.Ldarg_1);
338+
setIl.Emit(OpCodes.Stfld, backingField);
339+
setIl.Emit(OpCodes.Ret);
340+
341+
// Property
342+
PropertyBuilder propertyBuilder = typeBuilder.DefineProperty(propertyName, PropertyAttributes.None, propertyType, null);
343+
propertyBuilder.SetGetMethod(backingGet);
344+
propertyBuilder.SetSetMethod(backingSet);
345+
}
346+
}
347+
#endif
348+
349+
}
188350
#endif

src/ServiceStack.Text/PclExport.Net40.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,15 @@ public override SetPropertyDelegate GetSetMethod(PropertyInfo propertyInfo, Fiel
568568
: CreateIlFieldSetter(fieldInfo);
569569
}
570570

571+
public override Type UseType(Type type)
572+
{
573+
if (type.IsInterface || type.IsAbstract)
574+
{
575+
return DynamicProxy.GetInstanceFor(type).GetType();
576+
}
577+
return type;
578+
}
579+
571580
public override DataContractAttribute GetWeakDataContract(Type type)
572581
{
573582
return type.GetWeakDataContract();

src/ServiceStack.Text/ServiceStack.Text.PCL.csproj

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,6 @@
269269
<SubType>Code</SubType>
270270
</Compile>
271271
<Compile Include="ParseAsType.cs" />
272-
<Compile Include="DynamicProxy.cs" />
273272
<Compile Include="PclExport.NetStandard.cs" />
274273
</ItemGroup>
275274
<!--ItemGroup,Content-->

src/ServiceStack.Text/ServiceStack.Text.SL5.csproj

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -292,7 +292,6 @@
292292
<SubType>Code</SubType>
293293
</Compile>
294294
<Compile Include="ParseAsType.cs" />
295-
<Compile Include="DynamicProxy.cs" />
296295
<Compile Include="PclExport.NetStandard.cs" />
297296
</ItemGroup>
298297
<!--ItemGroup,Content-->

src/ServiceStack.Text/ServiceStack.Text.Signed.csproj

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -328,7 +328,6 @@
328328
<SubType>Code</SubType>
329329
</Compile>
330330
<Compile Include="ParseAsType.cs" />
331-
<Compile Include="DynamicProxy.cs" />
332331
<Compile Include="PclExport.NetStandard.cs" />
333332
</ItemGroup>
334333
<ItemGroup>

src/ServiceStack.Text/ServiceStack.Text.csproj

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -322,7 +322,6 @@
322322
<SubType>Code</SubType>
323323
</Compile>
324324
<Compile Include="ParseAsType.cs" />
325-
<Compile Include="DynamicProxy.cs" />
326325
<Compile Include="PclExport.NetStandard.cs" />
327326
</ItemGroup>
328327
<ItemGroup>

0 commit comments

Comments
 (0)