Skip to content

Instantly share code, notes, and snippets.

@antony-scott
Created February 10, 2021 10:17
Show Gist options
  • Save antony-scott/94fc60ce2f9624d0a81ee7f9e0564a9e to your computer and use it in GitHub Desktop.
Save antony-scott/94fc60ce2f9624d0a81ee7f9e0564a9e to your computer and use it in GitHub Desktop.
Create Proxy classes for Interfaces (properties only)
public static class Proxy
{
private static PropertyInfo[] GetProperties(Type type)
{
var list = type.GetProperties().ToList();
foreach (var intaface in type.GetInterfaces())
{
list.AddRange(GetProperties(intaface));
}
return list.Distinct().ToArray();
}
public static T For<T>(Action<T> initialiser = null)
{
var assemblyName = new AssemblyName(typeof(T).Name + "ProxyAssembly");
var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.RunAndSave);
var moduleBuilder = assemblyBuilder.DefineDynamicModule(typeof(T).Name + "ProxyModule");
var typeBuilder = moduleBuilder.DefineType(typeof(T).Name + "Proxy", TypeAttributes.Public);
typeBuilder.AddInterfaceImplementation(typeof(T));
var properties = GetProperties(typeof(T));
foreach (var property in properties)
{
var getSetAttr = MethodAttributes.Public | MethodAttributes.SpecialName | MethodAttributes.HideBySig | MethodAttributes.Virtual;
var fieldBuilder = typeBuilder.DefineField($"_{property.Name}", property.PropertyType, FieldAttributes.Private);
var propertyBuilder = typeBuilder.DefineProperty(property.Name, System.Reflection.PropertyAttributes.HasDefault, property.PropertyType, null);
{
var getMethodBuilder = typeBuilder.DefineMethod("get_" + property.Name, getSetAttr, property.PropertyType, Type.EmptyTypes);
var getter = getMethodBuilder.GetILGenerator();
getter.Emit(OpCodes.Ldarg_0);
getter.Emit(OpCodes.Ldfld, fieldBuilder);
getter.Emit(OpCodes.Ret);
propertyBuilder.SetGetMethod(getMethodBuilder);
}
{
var setMethodBuilder = typeBuilder.DefineMethod("set_" + property.Name, getSetAttr, null, new[] { property.PropertyType });
var setter = setMethodBuilder.GetILGenerator();
setter.Emit(OpCodes.Ldarg_0);
setter.Emit(OpCodes.Ldarg_1);
setter.Emit(OpCodes.Stfld, fieldBuilder);
setter.Emit(OpCodes.Ret);
propertyBuilder.SetSetMethod(setMethodBuilder);
}
}
var type = typeBuilder.CreateType();
T instance = (T)Activator.CreateInstance(type);
initialiser?.Invoke(instance);
return instance;
}
}
using System;
public interface IAmAnExample
{
Guid Id { get; set; }
string Name { get; set; }
}
public class ExampleTestFixture
{
[Test]
public void ProxyTest()
{
var example = Proxy.For<IAmAnExample>(x =>
{
x.Id = Guid.NewGuid();
x.Name = "Example";
});
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment