Skip to content

Instantly share code, notes, and snippets.

@ryanohs
Created April 2, 2016 15:31
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ryanohs/610d408d041c12076c098e0c6255a016 to your computer and use it in GitHub Desktop.
Save ryanohs/610d408d041c12076c098e0c6255a016 to your computer and use it in GitHub Desktop.
Playing with IL generation.
public class FastAccessor<T> where T : class
{
private static readonly Hashtable _cache = new Hashtable();
public static FastAccessor<T> For(T target)
{
if (_cache.ContainsKey(typeof(T)))
{
var dlg = (Action<T, string, object>)_cache[typeof(T)];
return new FastAccessor<T>(dlg, target);
}
var dlg2 = BuildDelegate<T>();
_cache[typeof(T)] = dlg2;
return new FastAccessor<T>(dlg2, target);
}
private static Action<T, string, object> BuildDelegate<T>()
{
var targetType = typeof(T);
var equality = typeof(string).GetMethod("op_Equality");
var method = IL.NewMethod()
.WithParameter<T>("target")
.WithParameter<string>("name")
.WithParameter<object>("value")
.Returns(typeof(void));
var properties = targetType.GetProperties();
var labels = Enumerable.Range(0, properties.Length).Select(p => $"label{p}").ToArray();
var i = 0;
foreach (var prop in properties)
{
method = method
.Ldarg("name")
.Ldstr(prop.Name)
.Call(equality)
.Brtrue(labels[i]);
i++;
}
method = method.Ret();
i = 0;
foreach (var prop in properties)
{
method = method
.MarkLabel(labels[i])
.Ldarg("target")
.Ldarg("value");
if (prop.PropertyType.IsValueType)
{
method = method.UnboxAny(prop.PropertyType);
}
else
{
method = method.Emit(OpCodes.Castclass, prop.PropertyType);
}
var setter = typeof(T).GetMethod("set_" + prop.Name);
method = method
.Callvirt(setter)
.Ret();
i++;
}
return (Action<T, string, object>)method.AsDynamicMethod.CreateDelegate(typeof(Action<T, string, object>));
}
private readonly Action<T, string, object> _action;
private readonly T _target;
private FastAccessor(Action<T, string, object> action, T target)
{
_action = action;
_target = target;
}
public void Set(string name, object value)
{
_action.Invoke(_target, name, value);
}
}
@unosbaghaie
Copy link

Hi
Is there IL class in .net core ?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment