Created
February 10, 2021 10:17
-
-
Save antony-scott/94fc60ce2f9624d0a81ee7f9e0564a9e to your computer and use it in GitHub Desktop.
Create Proxy classes for Interfaces (properties only)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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; | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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