mirror of https://github.com/AMT-Cheif/Stylet.git
Work implementating IoC container.
Still in the proof-of-concept stages, but working out quite well
This commit is contained in:
parent
fee276b7a9
commit
f3a5e8a584
|
@ -61,6 +61,7 @@
|
||||||
<Compile Include="PropertyChangedBase.cs" />
|
<Compile Include="PropertyChangedBase.cs" />
|
||||||
<Compile Include="Screen.cs" />
|
<Compile Include="Screen.cs" />
|
||||||
<Compile Include="ScreenExtensions.cs" />
|
<Compile Include="ScreenExtensions.cs" />
|
||||||
|
<Compile Include="StyletIoC.cs" />
|
||||||
<Compile Include="View.cs" />
|
<Compile Include="View.cs" />
|
||||||
<Compile Include="ViewLocator.cs" />
|
<Compile Include="ViewLocator.cs" />
|
||||||
<Compile Include="ViewModelBinder.cs" />
|
<Compile Include="ViewModelBinder.cs" />
|
||||||
|
|
|
@ -0,0 +1,186 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Linq.Expressions;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace Stylet
|
||||||
|
{
|
||||||
|
public class StyletIoC
|
||||||
|
{
|
||||||
|
private Dictionary<Type, IRegistration> registrations = new Dictionary<Type, IRegistration>();
|
||||||
|
|
||||||
|
public void Bind<TInterface, TImplementation>()
|
||||||
|
{
|
||||||
|
Type interfaceType = typeof(TInterface);
|
||||||
|
Type implementationType = typeof(TImplementation);
|
||||||
|
|
||||||
|
if (!interfaceType.IsAssignableFrom(implementationType))
|
||||||
|
throw new Exception(String.Format("Type {0} does not implement interface {1}", implementationType.Name, interfaceType.Name));
|
||||||
|
|
||||||
|
this.registrations.Add(interfaceType, new TransientRegistration(new TypeCreator(implementationType)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void BindSingleton<TInterface, TImplementation>()
|
||||||
|
{
|
||||||
|
Type interfaceType = typeof(TInterface);
|
||||||
|
Type implementationType = typeof(TImplementation);
|
||||||
|
|
||||||
|
if (!interfaceType.IsAssignableFrom(implementationType))
|
||||||
|
throw new Exception(String.Format("Type {0} does not implement interface {1}", implementationType.Name, interfaceType.Name));
|
||||||
|
|
||||||
|
this.registrations.Add(interfaceType, new SingletonRegistration<TImplementation>(new TypeCreator(implementationType)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void BindFactory<TInterface, TImplementation>(Func<StyletIoC, TImplementation> factory)
|
||||||
|
{
|
||||||
|
Type interfaceType = typeof(TInterface);
|
||||||
|
Type implementationType = typeof(TImplementation);
|
||||||
|
|
||||||
|
this.registrations.Add(interfaceType, new TransientRegistration(new FactoryCreator<TImplementation>(factory)));
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Compile()
|
||||||
|
{
|
||||||
|
foreach (var registration in this.registrations.Values)
|
||||||
|
{
|
||||||
|
registration.EnsureGenerator(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public object Get(Type type)
|
||||||
|
{
|
||||||
|
return this.registrations[type].Generator();
|
||||||
|
}
|
||||||
|
|
||||||
|
public T Get<T>()
|
||||||
|
{
|
||||||
|
return (T)this.Get(typeof(T));
|
||||||
|
}
|
||||||
|
|
||||||
|
private Expression GetExpression(Type type)
|
||||||
|
{
|
||||||
|
var registration = this.registrations[type];
|
||||||
|
return registration.GetInstanceExpression(this);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
private interface IRegistration
|
||||||
|
{
|
||||||
|
Func<object> Generator { get; }
|
||||||
|
void EnsureGenerator(StyletIoC service);
|
||||||
|
Expression GetInstanceExpression(StyletIoC service);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TransientRegistration : IRegistration
|
||||||
|
{
|
||||||
|
private ICreator creator;
|
||||||
|
public Func<object> Generator { get; private set;}
|
||||||
|
|
||||||
|
public TransientRegistration(ICreator creator)
|
||||||
|
{
|
||||||
|
this.creator = creator;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Expression GetInstanceExpression(StyletIoC service)
|
||||||
|
{
|
||||||
|
return this.creator.GetInstanceExpression(service);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void EnsureGenerator(StyletIoC service)
|
||||||
|
{
|
||||||
|
this.Generator = Expression.Lambda<Func<object>>(this.GetInstanceExpression(service)).Compile();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class SingletonRegistration<T> : IRegistration
|
||||||
|
{
|
||||||
|
private ICreator creator;
|
||||||
|
private T instance;
|
||||||
|
private Expression instanceExpression;
|
||||||
|
public Func<object> Generator { get; private set; }
|
||||||
|
|
||||||
|
|
||||||
|
public SingletonRegistration(ICreator creator)
|
||||||
|
{
|
||||||
|
this.creator = creator;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void EnsureInstantiated(StyletIoC service)
|
||||||
|
{
|
||||||
|
if (this.instance == null)
|
||||||
|
this.instance = Expression.Lambda<Func<T>>(this.creator.GetInstanceExpression(service)).Compile()();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void EnsureGenerator(StyletIoC service)
|
||||||
|
{
|
||||||
|
if (this.Generator != null)
|
||||||
|
return;
|
||||||
|
|
||||||
|
this.EnsureInstantiated(service);
|
||||||
|
this.Generator = () => this.instance;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Expression GetInstanceExpression(StyletIoC service)
|
||||||
|
{
|
||||||
|
if (this.instanceExpression != null)
|
||||||
|
return this.instanceExpression;
|
||||||
|
|
||||||
|
this.EnsureInstantiated(service);
|
||||||
|
|
||||||
|
this.instanceExpression = Expression.Constant(this.instance);
|
||||||
|
return this.instanceExpression;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private interface ICreator
|
||||||
|
{
|
||||||
|
Expression GetInstanceExpression(StyletIoC service);
|
||||||
|
}
|
||||||
|
|
||||||
|
private class TypeCreator : ICreator
|
||||||
|
{
|
||||||
|
private Type type;
|
||||||
|
private Expression creationExpression;
|
||||||
|
|
||||||
|
public TypeCreator(Type type)
|
||||||
|
{
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Expression GetInstanceExpression(StyletIoC service)
|
||||||
|
{
|
||||||
|
if (this.creationExpression != null)
|
||||||
|
return this.creationExpression;
|
||||||
|
|
||||||
|
// Pick a suitable one
|
||||||
|
var ctor = this.type.GetConstructors()[0];
|
||||||
|
// Check for loops
|
||||||
|
// Check for default values
|
||||||
|
var ctorParams = ctor.GetParameters().Select(x => service.GetExpression(x.ParameterType));
|
||||||
|
var creator = Expression.New(ctor, ctorParams);
|
||||||
|
this.creationExpression = creator;
|
||||||
|
return creator;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private class FactoryCreator<T> : ICreator
|
||||||
|
{
|
||||||
|
private Func<StyletIoC, T> factory;
|
||||||
|
|
||||||
|
public FactoryCreator(Func<StyletIoC, T> factory)
|
||||||
|
{
|
||||||
|
this.factory = factory;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Expression GetInstanceExpression(StyletIoC service)
|
||||||
|
{
|
||||||
|
var expr = (Expression<Func<T>>)(() => this.factory(service));
|
||||||
|
return expr;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -0,0 +1,41 @@
|
||||||
|
using NUnit.Framework;
|
||||||
|
using Stylet;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace StyletUnitTests
|
||||||
|
{
|
||||||
|
[TestFixture]
|
||||||
|
public class StyletIoCTests
|
||||||
|
{
|
||||||
|
[Test]
|
||||||
|
public void Temp()
|
||||||
|
{
|
||||||
|
var ioc = new StyletIoC();
|
||||||
|
ioc.BindSingleton<Dummy1, Dummy1>();
|
||||||
|
//ioc.Bind<Dummy2, Dummy2>();
|
||||||
|
ioc.BindFactory<Dummy2, Dummy2>(c => new Dummy2(c.Get<Dummy1>()));
|
||||||
|
|
||||||
|
ioc.Compile();
|
||||||
|
|
||||||
|
var two = ioc.Get<Dummy2>();
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Dummy1
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private class Dummy2
|
||||||
|
{
|
||||||
|
public Dummy1 Dummy1;
|
||||||
|
|
||||||
|
public Dummy2(Dummy1 dummy1)
|
||||||
|
{
|
||||||
|
this.Dummy1 = dummy1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -46,6 +46,7 @@
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Include="BindableCollectionTests.cs" />
|
<Compile Include="BindableCollectionTests.cs" />
|
||||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||||
|
<Compile Include="StyletIoCTests.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="packages.config" />
|
<None Include="packages.config" />
|
||||||
|
|
Loading…
Reference in New Issue