patterncsharpMinor
Unity Lazy Resolve Implementation
Viewed 0 times
lazyresolveunityimplementation
Problem
I have been using
Suggested lazy implementation by microsoft Deferring the Resolution of Objects
So I decided to start from scratch.
Firstly I needed an
We then need an interface and a type that is both
I now need a factory which creates the implementation of the
```
public class LazyTypeFactory
{
//used to stop the same class being created twice
private readonly object _lock = new object();
private readonly Dictionary _lazyTypes = new Dictionary();
private readonly ModuleBuilder _moduleBuilder;
public LazyTypeFactory(string assembly, string module)
{
var an = new AssemblyName(assembly);
var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(an, AssemblyBuilderAccess.Run);
_moduleBuilder = assemblyBuilder.DefineDynamicModule(module);
}
public Type CreateOrGetLazyType(string name = null)
where TLazy : ILazy, TInterface
where TInterface : class
{
Type result;
var @interface = typeof (TInterface);
var @container = typeof (IUni
Microsoft.Unity as my container and have decided that the approach for a lazy implementation causes too much rework. Each time you decide to swap out to use a lazy you have to go add .Value or a .Resolve() after your variable (which could be called hundreds of times).Suggested lazy implementation by microsoft Deferring the Resolution of Objects
So I decided to start from scratch.
Firstly I needed an
ILazy interface (I did add the Value property so you can get the actual value if it is ever needed)public interface ILazy where TInterface : class
{
TInterface Value { get; }
}We then need an interface and a type that is both
ILazy and of the interface to be implemented.public interface IContract
{
//methods and properties to be implemented
void SomeFunction();
}
public interface ILazyContract : ILazy, IContract
{
}
public class ContractImplementation : IContract
{
public void SomeFunction()
{
Console.WriteLine("Doing something");
}
}I now need a factory which creates the implementation of the
ILazyContract at runtime. This is a long class and has a bit of il generation so it might be difficult to read.```
public class LazyTypeFactory
{
//used to stop the same class being created twice
private readonly object _lock = new object();
private readonly Dictionary _lazyTypes = new Dictionary();
private readonly ModuleBuilder _moduleBuilder;
public LazyTypeFactory(string assembly, string module)
{
var an = new AssemblyName(assembly);
var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(an, AssemblyBuilderAccess.Run);
_moduleBuilder = assemblyBuilder.DefineDynamicModule(module);
}
public Type CreateOrGetLazyType(string name = null)
where TLazy : ILazy, TInterface
where TInterface : class
{
Type result;
var @interface = typeof (TInterface);
var @container = typeof (IUni
Solution
I think you might have a performance problem with
While I'm building a type, no one can grab a lazy type from the dictionary. That might become as problem as the IL generation is, as said above, kinda slow.
I'd change :
to :
Now yeah, duplicated code, I know! But sit awhile and listen. :p What's the advantage of this over your current solution? Your first scenario, the one where the dictionary contains the key, can be executed without caring about the
Of course, in my case we need to re-check inside the lock if the key was added meanwhile. If so, we return it.
Also, nesting 101 : Nesting is bad. Avoid it when you can. In your case, you can afford to remove a
CreateOrGetLazyType. Obviously, I'm not talking about the IL generation, we know that's not particularly fast. I'm talking about the lock statement.While I'm building a type, no one can grab a lazy type from the dictionary. That might become as problem as the IL generation is, as said above, kinda slow.
I'd change :
lock (_lock)
{
if (_lazyTypes.ContainsKey(@lazy))
{
result = _lazyTypes[@lazy];
}
else
{
//creation and whatever
}
}to :
if (_lazyTypes.ContainsKey(@lazy))
{
result = _lazyTypes[@lazy];
}
else
{
lock (_lock)
{
if (_lazyTypes.ContainsKey(@lazy))
{
return _lazyTypes[@lazy];
}
//creation and whatever
}
}Now yeah, duplicated code, I know! But sit awhile and listen. :p What's the advantage of this over your current solution? Your first scenario, the one where the dictionary contains the key, can be executed without caring about the
lock. And that's good! You don't want one IL generation to block several calls to the dictionary!Of course, in my case we need to re-check inside the lock if the key was added meanwhile. If so, we return it.
Also, nesting 101 : Nesting is bad. Avoid it when you can. In your case, you can afford to remove a
else statement. Instead of setting your result variable and returning it at the end of your method, you should return right away. This way you can remove the else. (That's what I did in my example).Code Snippets
lock (_lock)
{
if (_lazyTypes.ContainsKey(@lazy))
{
result = _lazyTypes[@lazy];
}
else
{
//creation and whatever
}
}if (_lazyTypes.ContainsKey(@lazy))
{
result = _lazyTypes[@lazy];
}
else
{
lock (_lock)
{
if (_lazyTypes.ContainsKey(@lazy))
{
return _lazyTypes[@lazy];
}
//creation and whatever
}
}Context
StackExchange Code Review Q#113343, answer score: 3
Revisions (0)
No revisions yet.