Skip to content

Commit

Permalink
micro Ioc container for Expressmapper
Browse files Browse the repository at this point in the history
  • Loading branch information
anisimovyuriy committed Jun 29, 2015
1 parent e01a75b commit 7a96a69
Show file tree
Hide file tree
Showing 4 changed files with 143 additions and 0 deletions.
11 changes: 11 additions & 0 deletions ExpressMapper NET40/Constants.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace ExpressMapper
{
public class Constants
{
}
}
3 changes: 3 additions & 0 deletions ExpressMapper NET40/ExpressMapper NET40.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -51,9 +51,12 @@
</ItemGroup>
<ItemGroup>
<Compile Include="CollectionTypes.cs" />
<Compile Include="Constants.cs" />
<Compile Include="DefaultMappingContext.cs" />
<Compile Include="IMappingContext.cs" />
<Compile Include="IMappingService.cs" />
<Compile Include="Ioc\DependencyResolver.cs" />
<Compile Include="Ioc\IContainer.cs" />
<Compile Include="MapNotImplemented.cs" />
<Compile Include="MappingService.cs" />
<Compile Include="NullCheckNestedMemberVisitor.cs">
Expand Down
115 changes: 115 additions & 0 deletions ExpressMapper NET40/Ioc/DependencyResolver.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;
using System.Reflection;

namespace ExpressMapper.Ioc
{
public class DependencyResolver : IContainer
{
#region Constructors

private DependencyResolver()
{
Initialize();
}

#endregion

#region Privates

private readonly Dictionary<int, Dictionary<int, Delegate>> _cache = new Dictionary<int, Dictionary<int, Delegate>>();
private static IContainer _container;

#endregion

internal static IContainer GetContainer()
{
return _container ?? (_container = new DependencyResolver());
}

public T Resolve<T>()
{
var interfHash = typeof(T).GetHashCode();
NotImplementedCheck(interfHash, typeof(T).FullName);
MoreThanOnImplCheck(interfHash, typeof(T).FullName);

var implInstance = (T)_cache[interfHash].First().Value.DynamicInvoke();
return implInstance;
}

#region Checks and throw exceptions

private void MoreThanOnImplCheck(int interfHash, string typeFullName)
{
if (_cache[interfHash].Count > 1)
{
throw new NotImplementedException(
string.Format("There more than one implementation have been found for the {0} interface.",
typeFullName));
}
}

private void NotImplementedCheck(int interfHash, string typeFullName)
{
if (!_cache.ContainsKey(interfHash) || _cache[interfHash].Count == 0)
{
throw new NotImplementedException(
string.Format("No implementation has been found for the {0} interface.", typeFullName));
}

}

#endregion

public IEnumerable<T> ResolveAll<T>()
{
var interfHash = typeof(T).GetHashCode();
NotImplementedCheck(interfHash, typeof(T).FullName);
var implArray = new T[_cache[interfHash].Count];
for (var i = 0; i < _cache[interfHash].Values.Count; i++)
{
implArray[i] = (T) _cache[interfHash].Values.ElementAt(i).DynamicInvoke();
}
return implArray;
}

#region Initialization and compilation
private void Initialize()
{
var expressMapperAssembly = Assembly.GetExecutingAssembly();
var expressInterfaces = expressMapperAssembly.GetTypes().Where(t => t.IsInterface);
foreach (var expressInterface in expressInterfaces)
{
var implementations = expressMapperAssembly.GetTypes().Where(t => expressInterface.IsAssignableFrom(t));
Compile(expressInterface, implementations);
}

}

private void Compile(Type inter, IEnumerable<Type> implementations)
{
foreach (var impl in implementations)
{
var interHash = inter.GetHashCode();
if (!_cache.ContainsKey(interHash))
{
_cache[interHash] = new Dictionary<int, Delegate>();
}

var implHash = impl.GetHashCode();

if (!_cache[interHash].ContainsKey(implHash))
{
var newExpression = Expression.New(impl);
var lambdaExpression = Expression.Lambda(newExpression);
var del = lambdaExpression.Compile();
_cache[interHash][implHash] = del;
}
}
}

#endregion
}
}
14 changes: 14 additions & 0 deletions ExpressMapper NET40/Ioc/IContainer.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;

namespace ExpressMapper.Ioc
{
public interface IContainer
{
T Resolve<T>();
IEnumerable<T> ResolveAll<T>();
}
}

0 comments on commit 7a96a69

Please sign in to comment.