While doing some rework suggested by Heslacher, I saw an opportunity to clean up some of the intermediate language generation.
It is much easier to read and debug a class that is not generated at runtime.
While doing some rework suggested by Heslacher, I saw an opportunity to clean up some of the intermediate language generation.
It is much easier to read and debug a class that is not generated at runtime.
While doing some rework suggested by Heslacher, I saw an opportunity to clean up some of the intermediate language generation.
It is much easier to read and debug a class that is not generated at runtime.
So I added an implementation for ILazy<T>
and extended this class when creating the lazy implementation of an interface.
public class Lazy<TInterface> : ILazy<TInterface>
where TInterface : class
{
private readonly object _lock = new object();
private bool _isSet = false;
private readonly IUnityContainer _container;
private readonly Func<IUnityContainer, TInterface> _func;
private TInterface _value;
public Lazy(IUnityContainer container, Func<IUnityContainer, TInterface> func)
{
_container = container;
_func = func;
}
public TInterface Value
{
get
{
//quick check so that lock is not called
if (_isSet)
{
return _value;
}
lock (_lock)
{
//double check for certainty
if (_isSet)
{
return _value;
}
_value = _func(_container);
_isSet = true;
}
return _value;
}
}
}
I then set it as the base class when I create my TypeBuilder
var @lazyInterface = typeof(Lazy<TInterface>);
var typeBuilder = _moduleBuilder.DefineType(name, TypeAttributes.Public | TypeAttributes.Class, @lazyInterface);
This clears up all the private FieldBuilder
s and the PropertyBuilder
.
This therefore also cleans up much of the il generation.
This did mean that I have to update my CreateConstructor
method as such.
But this turned out to be better as well imo.
private static void CreateConstructor(TypeBuilder typeBuilder, Type @container, Type @func, ConstructorInfo baseConstructor)
{
var constructor = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard | CallingConventions.HasThis, new[] { @container, @func });
constructor.DefineParameter(1, ParameterAttributes.None, "container");
constructor.DefineParameter(2, ParameterAttributes.None, "func");
var cIl = constructor.GetILGenerator();
cIl.Emit(OpCodes.Ldarg_0);
cIl.Emit(OpCodes.Ldarg_1);
cIl.Emit(OpCodes.Ldarg_2);
cIl.Emit(OpCodes.Call, baseConstructor);
cIl.Emit(OpCodes.Ret);
}