mirror of https://github.com/AMT-Cheif/Stylet.git
Reflector StyletIoC into multiple implementation files
This commit is contained in:
parent
374f5d9049
commit
a73a5f65d9
|
@ -61,7 +61,13 @@
|
|||
<Compile Include="PropertyChangedBase.cs" />
|
||||
<Compile Include="Screen.cs" />
|
||||
<Compile Include="ScreenExtensions.cs" />
|
||||
<Compile Include="StyletIoC.cs" />
|
||||
<Compile Include="StyletIoC\BuilderUpper.cs" />
|
||||
<Compile Include="StyletIoC\ICreator.cs" />
|
||||
<Compile Include="StyletIoC\IRegistration.cs" />
|
||||
<Compile Include="StyletIoC\IRegistrationCollection.cs" />
|
||||
<Compile Include="StyletIoC\StyletIoCBindTo.cs" />
|
||||
<Compile Include="StyletIoC\StyletIoCContainer.cs" />
|
||||
<Compile Include="StyletIoC\UnboundGeneric.cs" />
|
||||
<Compile Include="View.cs" />
|
||||
<Compile Include="ViewLocator.cs" />
|
||||
<Compile Include="ViewModelBinder.cs" />
|
||||
|
|
1083
Stylet/StyletIoC.cs
1083
Stylet/StyletIoC.cs
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,63 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StyletIoC
|
||||
{
|
||||
internal class BuilderUpper
|
||||
{
|
||||
private Type type;
|
||||
private StyletIoCContainer container;
|
||||
private Action<object> implementor;
|
||||
|
||||
public BuilderUpper(Type type, StyletIoCContainer container)
|
||||
{
|
||||
this.type = type;
|
||||
this.container = container;
|
||||
}
|
||||
|
||||
public Expression GetExpression(Expression inputParameterExpression)
|
||||
{
|
||||
var expressions = this.type.GetFields(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance).Select(x => this.ExpressionForMember(inputParameterExpression, x, x.FieldType))
|
||||
.Concat(this.type.GetProperties(BindingFlags.NonPublic | BindingFlags.Public | BindingFlags.Instance).Select(x => this.ExpressionForMember(inputParameterExpression, x, x.PropertyType)))
|
||||
.Where(x => x != null);
|
||||
|
||||
// Sadly, we can't cache this expression (I think), as it relies on the inputParameterExpression
|
||||
// which is likely to change between calls
|
||||
// This isn't so bad, so we'll (probably) only need to call this at most twice - once for building up the type on creation,
|
||||
// and once for creating the implemtor (which is used in BuildUp())
|
||||
if (!expressions.Any())
|
||||
return Expression.Empty();
|
||||
return Expression.Block(expressions);
|
||||
}
|
||||
|
||||
private Expression ExpressionForMember(Expression objExpression, MemberInfo member, Type memberType)
|
||||
{
|
||||
var attribute = member.GetCustomAttribute<InjectAttribute>(true);
|
||||
if (attribute == null)
|
||||
return null;
|
||||
|
||||
var valueExpression = this.container.GetExpression(new TypeKey(memberType, attribute.Key), true);
|
||||
var memberAccess = Expression.MakeMemberAccess(objExpression, member);
|
||||
var memberValue = this.container.GetExpression(new TypeKey(memberType, attribute.Key), true);
|
||||
return Expression.Assign(memberAccess, memberValue);
|
||||
}
|
||||
|
||||
public Action<object> GetImplementor()
|
||||
{
|
||||
if (this.implementor != null)
|
||||
return this.implementor;
|
||||
|
||||
var parameterExpression = Expression.Parameter(typeof(object), "inputParameter");
|
||||
var typedParameterExpression = Expression.Convert(parameterExpression, this.type);
|
||||
var expression = this.GetExpression(typedParameterExpression);
|
||||
this.implementor = Expression.Lambda<Action<object>>(this.GetExpression(typedParameterExpression), parameterExpression).Compile();
|
||||
|
||||
return this.implementor;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,147 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StyletIoC
|
||||
{
|
||||
internal interface ICreator
|
||||
{
|
||||
Type Type { get; }
|
||||
Expression GetInstanceExpression();
|
||||
}
|
||||
|
||||
internal abstract class CreatorBase : ICreator
|
||||
{
|
||||
public virtual Type Type { get; protected set; }
|
||||
|
||||
public abstract Expression GetInstanceExpression();
|
||||
}
|
||||
|
||||
internal class TypeCreator : CreatorBase
|
||||
{
|
||||
private StyletIoCContainer container;
|
||||
public string AttributeKey { get; private set; }
|
||||
private Expression creationExpression;
|
||||
|
||||
public TypeCreator(Type type, StyletIoCContainer container)
|
||||
{
|
||||
this.Type = type;
|
||||
this.container = container;
|
||||
|
||||
// Use the key from InjectAttribute (if present), and let someone else override it if they want
|
||||
var attribute = (InjectAttribute)type.GetCustomAttributes(typeof(InjectAttribute), false).FirstOrDefault();
|
||||
if (attribute != null)
|
||||
this.AttributeKey = attribute.Key;
|
||||
}
|
||||
|
||||
private string KeyForParameter(ParameterInfo parameter)
|
||||
{
|
||||
var attributes = parameter.GetCustomAttributes(typeof(InjectAttribute));
|
||||
if (attributes == null)
|
||||
return null;
|
||||
var attribute = (InjectAttribute)attributes.FirstOrDefault();
|
||||
return attribute == null ? null : attribute.Key;
|
||||
}
|
||||
|
||||
public override Expression GetInstanceExpression()
|
||||
{
|
||||
if (this.creationExpression != null)
|
||||
return this.creationExpression;
|
||||
|
||||
// Find the constructor which has the most parameters which we can fulfill, accepting default values which we can't fulfill
|
||||
ConstructorInfo ctor;
|
||||
var ctorsWithAttribute = this.Type.GetConstructors().Where(x => x.GetCustomAttributes(typeof(InjectAttribute), false).Any()).ToList();
|
||||
if (ctorsWithAttribute.Count > 1)
|
||||
{
|
||||
throw new StyletIoCFindConstructorException(String.Format("Found more than one constructor with [Inject] on type {0}.", this.Type.Name));
|
||||
}
|
||||
else if (ctorsWithAttribute.Count == 1)
|
||||
{
|
||||
ctor = ctorsWithAttribute[0];
|
||||
var key = ((InjectAttribute)ctorsWithAttribute[0].GetCustomAttribute(typeof(InjectAttribute), false)).Key;
|
||||
var cantResolve = ctor.GetParameters().Where(p => !this.container.CanResolve(new TypeKey(p.ParameterType, key)) && !p.HasDefaultValue).FirstOrDefault();
|
||||
if (cantResolve != null)
|
||||
throw new StyletIoCFindConstructorException(String.Format("Found a constructor with [Inject] on type {0}, but can't resolve parameter '{1}' (which doesn't have a default value).", this.Type.Name, cantResolve.Name));
|
||||
}
|
||||
else
|
||||
{
|
||||
ctor = this.Type.GetConstructors()
|
||||
.Where(c => c.GetParameters().All(p => this.container.CanResolve(new TypeKey(p.ParameterType, this.KeyForParameter(p))) || p.HasDefaultValue))
|
||||
.OrderByDescending(c => c.GetParameters().Count(p => !p.HasDefaultValue))
|
||||
.FirstOrDefault();
|
||||
|
||||
if (ctor == null)
|
||||
{
|
||||
throw new StyletIoCFindConstructorException(String.Format("Unable to find a constructor for type {0} which we can call.", this.Type.Name));
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Check for loops
|
||||
|
||||
// If there parameter's got an InjectAttribute with a key, use that key to resolve
|
||||
var ctorParams = ctor.GetParameters().Select(x =>
|
||||
{
|
||||
var key = this.KeyForParameter(x);
|
||||
if (this.container.CanResolve(new TypeKey(x.ParameterType, key)))
|
||||
{
|
||||
try
|
||||
{
|
||||
return this.container.GetExpression(new TypeKey(x.ParameterType, key), true);
|
||||
}
|
||||
catch (StyletIoCRegistrationException e)
|
||||
{
|
||||
throw new StyletIoCRegistrationException(String.Format("{0} Required by paramter '{1}' of type {2}.", e.Message, x.Name, this.Type.Name), e);
|
||||
}
|
||||
}
|
||||
// For some reason we need this cast...
|
||||
return Expression.Convert(Expression.Constant(x.DefaultValue), x.ParameterType);
|
||||
});
|
||||
|
||||
var instanceVar = Expression.Variable(this.Type, "instance");
|
||||
var creator = Expression.New(ctor, ctorParams);
|
||||
var assignment = Expression.Assign(instanceVar, creator);
|
||||
|
||||
var buildUpExpression = this.container.GetBuilderUpper(this.Type).GetExpression(instanceVar);
|
||||
|
||||
// We always start with:
|
||||
// var instance = new Class(.....)
|
||||
// instance.Property1 = new ....
|
||||
// instance.Property2 = new ....
|
||||
var blockItems = new List<Expression>() { assignment, buildUpExpression };
|
||||
// If it implements IInjectionAware, follow that up with:
|
||||
// instance.ParametersInjected
|
||||
if (typeof(IInjectionAware).IsAssignableFrom(this.Type))
|
||||
blockItems.Add(Expression.Call(instanceVar, typeof(IInjectionAware).GetMethod("ParametersInjected")));
|
||||
// Final appearance of instanceVar, as this sets the return value of the block
|
||||
blockItems.Add(instanceVar);
|
||||
var completeExpression = Expression.Block(new[] { instanceVar }, blockItems);
|
||||
|
||||
this.creationExpression = completeExpression;
|
||||
return completeExpression;
|
||||
}
|
||||
}
|
||||
|
||||
internal class FactoryCreator<T> : CreatorBase
|
||||
{
|
||||
private Func<StyletIoCContainer, T> factory;
|
||||
private StyletIoCContainer container;
|
||||
|
||||
public override Type Type { get { return typeof(T); } }
|
||||
|
||||
public FactoryCreator(Func<StyletIoCContainer, T> factory, StyletIoCContainer container)
|
||||
{
|
||||
this.factory = factory;
|
||||
this.container = container;
|
||||
}
|
||||
|
||||
public override Expression GetInstanceExpression()
|
||||
{
|
||||
var expr = (Expression<Func<T>>)(() => this.factory(this.container));
|
||||
return Expression.Invoke(expr, null);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,130 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StyletIoC
|
||||
{
|
||||
internal interface IRegistration
|
||||
{
|
||||
Type Type { get; }
|
||||
bool WasAutoCreated { get; set; }
|
||||
Func<object> GetGenerator();
|
||||
Expression GetInstanceExpression();
|
||||
}
|
||||
|
||||
internal abstract class RegistrationBase : IRegistration
|
||||
{
|
||||
protected ICreator creator;
|
||||
|
||||
public Type Type { get { return this.creator.Type; } }
|
||||
public bool WasAutoCreated { get; set; }
|
||||
|
||||
protected Func<object> generator { get; set; }
|
||||
|
||||
public RegistrationBase(ICreator creator)
|
||||
{
|
||||
this.creator = creator;
|
||||
}
|
||||
|
||||
public abstract Func<object> GetGenerator();
|
||||
public abstract Expression GetInstanceExpression();
|
||||
}
|
||||
|
||||
|
||||
internal class TransientRegistration : RegistrationBase
|
||||
{
|
||||
public TransientRegistration(ICreator creator) : base(creator) { }
|
||||
|
||||
public override Expression GetInstanceExpression()
|
||||
{
|
||||
return this.creator.GetInstanceExpression();
|
||||
}
|
||||
|
||||
public override Func<object> GetGenerator()
|
||||
{
|
||||
if (this.generator == null)
|
||||
this.generator = Expression.Lambda<Func<object>>(this.GetInstanceExpression()).Compile();
|
||||
return this.generator;
|
||||
}
|
||||
}
|
||||
|
||||
internal class SingletonRegistration : RegistrationBase
|
||||
{
|
||||
private object instance;
|
||||
private Expression instanceExpression;
|
||||
|
||||
public SingletonRegistration(ICreator creator) : base(creator) { }
|
||||
|
||||
private void EnsureInstantiated()
|
||||
{
|
||||
if (this.instance != null)
|
||||
return;
|
||||
|
||||
// Ensure we don't end up creating two singletons, one used by each thread
|
||||
Interlocked.CompareExchange(ref this.instance, Expression.Lambda<Func<object>>(this.creator.GetInstanceExpression()).Compile()(), null);
|
||||
}
|
||||
|
||||
public override Func<object> GetGenerator()
|
||||
{
|
||||
this.EnsureInstantiated();
|
||||
|
||||
if (this.generator == null)
|
||||
this.generator = () => this.instance;
|
||||
|
||||
return this.generator;
|
||||
}
|
||||
|
||||
public override Expression GetInstanceExpression()
|
||||
{
|
||||
if (this.instanceExpression != null)
|
||||
return this.instanceExpression;
|
||||
|
||||
this.EnsureInstantiated();
|
||||
|
||||
// This expression yields the actual type of instance, not 'object'
|
||||
this.instanceExpression = Expression.Constant(this.instance);
|
||||
return this.instanceExpression;
|
||||
}
|
||||
}
|
||||
|
||||
internal class GetAllRegistration : IRegistration
|
||||
{
|
||||
private StyletIoCContainer container;
|
||||
|
||||
public string Key { get; set; }
|
||||
public Type Type { get; private set; }
|
||||
public bool WasAutoCreated { get; set; }
|
||||
|
||||
private Expression expression;
|
||||
private Func<object> generator;
|
||||
|
||||
public GetAllRegistration(Type type, StyletIoCContainer container)
|
||||
{
|
||||
this.Type = type;
|
||||
this.container = container;
|
||||
}
|
||||
|
||||
public Func<object> GetGenerator()
|
||||
{
|
||||
if (this.generator == null)
|
||||
this.generator = Expression.Lambda<Func<object>>(this.GetInstanceExpression()).Compile();
|
||||
return this.generator;
|
||||
}
|
||||
|
||||
public Expression GetInstanceExpression()
|
||||
{
|
||||
if (this.expression != null)
|
||||
return this.expression;
|
||||
|
||||
var list = Expression.New(this.Type);
|
||||
var init = Expression.ListInit(list, this.container.GetRegistrations(new TypeKey(this.Type.GenericTypeArguments[0], this.Key), false).GetAll().Select(x => x.GetInstanceExpression()));
|
||||
|
||||
this.expression = init;
|
||||
return this.expression;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,81 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StyletIoC
|
||||
{
|
||||
internal interface IRegistrationCollection
|
||||
{
|
||||
IRegistration GetSingle();
|
||||
List<IRegistration> GetAll();
|
||||
IRegistrationCollection AddRegistration(IRegistration registration);
|
||||
}
|
||||
|
||||
internal class SingleRegistration : IRegistrationCollection
|
||||
{
|
||||
private IRegistration registration;
|
||||
|
||||
public SingleRegistration(IRegistration registration)
|
||||
{
|
||||
this.registration = registration;
|
||||
}
|
||||
|
||||
public IRegistration GetSingle()
|
||||
{
|
||||
return this.registration;
|
||||
}
|
||||
|
||||
public List<IRegistration> GetAll()
|
||||
{
|
||||
return new List<IRegistration>() { this.registration };
|
||||
}
|
||||
|
||||
public IRegistrationCollection AddRegistration(IRegistration registration)
|
||||
{
|
||||
return new RegistrationCollection(new List<IRegistration>() { this.registration, registration });
|
||||
}
|
||||
}
|
||||
|
||||
internal class RegistrationCollection : IRegistrationCollection
|
||||
{
|
||||
private List<IRegistration> registrations;
|
||||
|
||||
public RegistrationCollection(List<IRegistration> registrations)
|
||||
{
|
||||
this.registrations = registrations;
|
||||
}
|
||||
|
||||
public IRegistration GetSingle()
|
||||
{
|
||||
throw new StyletIoCRegistrationException("Multiple registrations found.");
|
||||
}
|
||||
|
||||
public List<IRegistration> GetAll()
|
||||
{
|
||||
List<IRegistration> registrationsCopy;
|
||||
lock (this.registrations) { registrationsCopy = registrations.ToList(); }
|
||||
return registrationsCopy;
|
||||
}
|
||||
|
||||
public IRegistrationCollection AddRegistration(IRegistration registration)
|
||||
{
|
||||
// Need to lock the list, as someone might be fetching from it while we do this
|
||||
lock (this.registrations)
|
||||
{
|
||||
// Is there an existing registration for this type?
|
||||
var existingRegistration = this.registrations.FirstOrDefault(x => x.Type == registration.Type);
|
||||
if (existingRegistration != null)
|
||||
{
|
||||
if (existingRegistration.WasAutoCreated)
|
||||
this.registrations.Remove(existingRegistration);
|
||||
else
|
||||
throw new StyletIoCRegistrationException(String.Format("Multiple registrations for type {0} found.", registration.Type.Name));
|
||||
}
|
||||
this.registrations.Add(registration);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,136 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StyletIoC
|
||||
{
|
||||
public interface IStyletIoCBindTo
|
||||
{
|
||||
void ToSelf(string key = null);
|
||||
void To<TImplementation>(string key = null) where TImplementation : class;
|
||||
void To(Type implementationType, string key = null);
|
||||
void ToFactory<TImplementation>(Func<IContainer, TImplementation> factory, string key = null) where TImplementation : class;
|
||||
void ToAbstractFactory(string key = null);
|
||||
void ToAllImplementations(string key = null, params Assembly[] assembly);
|
||||
}
|
||||
|
||||
public class StyletIoCBindTo : IStyletIoCBindTo
|
||||
{
|
||||
private StyletIoCContainer container;
|
||||
private Type serviceType;
|
||||
private bool isSingleton;
|
||||
|
||||
public StyletIoCBindTo(StyletIoCContainer service, Type serviceType, bool isSingleton)
|
||||
{
|
||||
this.container = service;
|
||||
this.serviceType = serviceType;
|
||||
this.isSingleton = isSingleton;
|
||||
}
|
||||
|
||||
public void ToSelf(string key = null)
|
||||
{
|
||||
this.To(this.serviceType, key);
|
||||
}
|
||||
|
||||
public void To<TImplementation>(string key = null) where TImplementation : class
|
||||
{
|
||||
this.To(typeof(TImplementation), key);
|
||||
}
|
||||
|
||||
public void To(Type implementationType, string key = null)
|
||||
{
|
||||
this.EnsureType(implementationType);
|
||||
if (this.serviceType.IsGenericTypeDefinition)
|
||||
{
|
||||
var unboundGeneric = new UnboundGeneric(implementationType, this.container, this.isSingleton);
|
||||
this.container.AddUnboundGeneric(new TypeKey(serviceType, key), unboundGeneric);
|
||||
}
|
||||
else
|
||||
{
|
||||
var creator = new TypeCreator(implementationType, this.container);
|
||||
this.AddRegistration(creator, implementationType, key ?? creator.AttributeKey);
|
||||
}
|
||||
}
|
||||
|
||||
public void ToFactory<TImplementation>(Func<IContainer, TImplementation> factory, string key = null) where TImplementation : class
|
||||
{
|
||||
Type implementationType = typeof(TImplementation);
|
||||
this.EnsureType(implementationType);
|
||||
if (this.serviceType.IsGenericTypeDefinition)
|
||||
throw new StyletIoCRegistrationException(String.Format("A factory cannot be used to implement unbound generic type {0}", this.serviceType.Name));
|
||||
var creator = new FactoryCreator<TImplementation>(factory, this.container);
|
||||
this.AddRegistration(creator, implementationType, key);
|
||||
}
|
||||
|
||||
public void ToAbstractFactory(string key = null)
|
||||
{
|
||||
var factoryType = this.container.GetFactoryForType(this.serviceType);
|
||||
this.To(factoryType, key);
|
||||
}
|
||||
|
||||
public void ToAllImplementations(string key = null, params Assembly[] assemblies)
|
||||
{
|
||||
if (assemblies == null || assemblies.Length == 0)
|
||||
assemblies = new[] { Assembly.GetCallingAssembly() };
|
||||
|
||||
var candidates = from type in assemblies.SelectMany(x => x.GetTypes())
|
||||
let baseType = type.GetBaseTypesAndInterfaces().FirstOrDefault(x => x == this.serviceType || x.IsGenericType && x.GetGenericTypeDefinition() == this.serviceType)
|
||||
where baseType != null
|
||||
select new { Type = type, Base = baseType.ContainsGenericParameters ? baseType.GetGenericTypeDefinition() : baseType };
|
||||
|
||||
foreach (var candidate in candidates)
|
||||
{
|
||||
try
|
||||
{
|
||||
this.container.Bind(candidate.Base).To(candidate.Type, key);
|
||||
}
|
||||
catch (StyletIoCRegistrationException e)
|
||||
{
|
||||
Debug.WriteLine(String.Format("Unable to auto-bind type {0} to {1}: {2}", candidate.Base.Name, candidate.Type.Name, e.Message), "StyletIoC");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void EnsureType(Type implementationType)
|
||||
{
|
||||
if (!implementationType.IsClass || implementationType.IsAbstract)
|
||||
throw new StyletIoCRegistrationException(String.Format("Type {0} is not a concrete class, and so can't be used to implemented service {1}", implementationType.Name, this.serviceType.Name));
|
||||
|
||||
// Test this first, as it's a bit clearer than hitting 'type doesn't implement service'
|
||||
if (implementationType.IsGenericTypeDefinition)
|
||||
{
|
||||
if (this.isSingleton)
|
||||
throw new StyletIoCRegistrationException(String.Format("You cannot create singleton registration for unbound generic type {0}", implementationType.Name));
|
||||
|
||||
if (!this.serviceType.IsGenericTypeDefinition)
|
||||
throw new StyletIoCRegistrationException(String.Format("You may not bind the unbound generic type {0} to the bound generic / non-generic service {1}", implementationType.Name, this.serviceType.Name));
|
||||
|
||||
// This restriction may change when I figure out how to pass down the correct type argument
|
||||
if (this.serviceType.GetTypeInfo().GenericTypeParameters.Length != implementationType.GetTypeInfo().GenericTypeParameters.Length)
|
||||
throw new StyletIoCRegistrationException(String.Format("If you're registering an unbound generic type to an unbound generic service, both service and type must have the same number of type parameters. Service: {0}, Type: {1}", this.serviceType.Name, implementationType.Name));
|
||||
}
|
||||
else if (this.serviceType.IsGenericTypeDefinition)
|
||||
{
|
||||
throw new StyletIoCRegistrationException(String.Format("You cannot bind the bound generic / non-generic type {0} to unbound generic service {1}", implementationType.Name, this.serviceType.Name));
|
||||
}
|
||||
|
||||
if (!implementationType.Implements(this.serviceType))
|
||||
throw new StyletIoCRegistrationException(String.Format("Type {0} does not implement service {1}", implementationType.Name, this.serviceType.Name));
|
||||
}
|
||||
|
||||
private void AddRegistration(ICreator creator, Type implementationType, string key)
|
||||
{
|
||||
IRegistration registration;
|
||||
if (this.isSingleton)
|
||||
registration = new SingletonRegistration(creator);
|
||||
else
|
||||
registration = new TransientRegistration(creator);
|
||||
|
||||
container.AddRegistration(new TypeKey(this.serviceType, key), registration);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,541 @@
|
|||
using System;
|
||||
using System.Collections.Concurrent;
|
||||
using System.Collections.Generic;
|
||||
using System.Diagnostics;
|
||||
using System.Linq;
|
||||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
using System.Reflection.Emit;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StyletIoC
|
||||
{
|
||||
public interface IContainer
|
||||
{
|
||||
IStyletIoCBindTo Bind<TService>();
|
||||
IStyletIoCBindTo Bind(Type serviceType);
|
||||
IStyletIoCBindTo BindSingleton<TService>();
|
||||
IStyletIoCBindTo BindSingleton(Type serviceType);
|
||||
|
||||
void AutoBind(params Assembly[] assemblies);
|
||||
|
||||
void Compile();
|
||||
object Get(Type type, string key = null);
|
||||
T Get<T>(string key = null);
|
||||
IEnumerable<object> GetAll(Type type, string key = null);
|
||||
IEnumerable<T> GetAll<T>(string key = null);
|
||||
object GetTypeOrAll(Type type, string key = null);
|
||||
T GetTypeOrAll<T>(string key = null);
|
||||
void BuildUp(object item);
|
||||
}
|
||||
|
||||
public class StyletIoCContainer : IContainer
|
||||
{
|
||||
public static readonly string FactoryAssemblyName = "StyletIoCFactory";
|
||||
|
||||
private ConcurrentDictionary<TypeKey, IRegistrationCollection> registrations = new ConcurrentDictionary<TypeKey, IRegistrationCollection>();
|
||||
private ConcurrentDictionary<TypeKey, IRegistration> getAllRegistrations = new ConcurrentDictionary<TypeKey, IRegistration>();
|
||||
// The list object is used for locking it
|
||||
private ConcurrentDictionary<TypeKey, List<UnboundGeneric>> unboundGenerics = new ConcurrentDictionary<TypeKey, List<UnboundGeneric>>();
|
||||
private ConcurrentDictionary<Type, BuilderUpper> builderUppers = new ConcurrentDictionary<Type, BuilderUpper>();
|
||||
|
||||
|
||||
private ModuleBuilder factoryBuilder;
|
||||
private ConcurrentDictionary<Type, Type> factories = new ConcurrentDictionary<Type, Type>();
|
||||
|
||||
private bool compilationStarted;
|
||||
|
||||
public StyletIoCContainer()
|
||||
{
|
||||
this.BindSingleton<IContainer>().ToFactory(c => this);
|
||||
}
|
||||
|
||||
public void AutoBind(params Assembly[] assemblies)
|
||||
{
|
||||
if (assemblies == null || assemblies.Length == 0)
|
||||
assemblies = new[] { Assembly.GetCallingAssembly() };
|
||||
|
||||
var classes = assemblies.SelectMany(x => x.GetTypes()).Where(c => c.IsClass && !c.IsAbstract);
|
||||
foreach (var cls in classes)
|
||||
{
|
||||
try
|
||||
{
|
||||
this.Bind(cls).To(cls);
|
||||
}
|
||||
catch (StyletIoCRegistrationException e)
|
||||
{
|
||||
Debug.WriteLine(String.Format("Unable to auto-bind type {0}: {1}", cls.Name, e.Message), "StyletIoC");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public IStyletIoCBindTo Bind<TService>()
|
||||
{
|
||||
return this.Bind(typeof(TService));
|
||||
}
|
||||
|
||||
public IStyletIoCBindTo Bind(Type serviceType)
|
||||
{
|
||||
this.CheckCompilationStarted();
|
||||
return new StyletIoCBindTo(this, serviceType, false);
|
||||
}
|
||||
|
||||
public IStyletIoCBindTo BindSingleton<TService>()
|
||||
{
|
||||
return this.BindSingleton(typeof(TService));
|
||||
}
|
||||
|
||||
public IStyletIoCBindTo BindSingleton(Type serviceType)
|
||||
{
|
||||
this.CheckCompilationStarted();
|
||||
return new StyletIoCBindTo(this, serviceType, true);
|
||||
}
|
||||
|
||||
private void CheckCompilationStarted()
|
||||
{
|
||||
if (this.compilationStarted)
|
||||
throw new StyletIoCException("Once you've started to retrieve items from the container, or have called Compile(), you cannot register new services");
|
||||
}
|
||||
|
||||
public void Compile()
|
||||
{
|
||||
this.compilationStarted = true;
|
||||
foreach (var kvp in this.registrations)
|
||||
{
|
||||
foreach (var registration in kvp.Value.GetAll())
|
||||
{
|
||||
try
|
||||
{
|
||||
registration.GetGenerator();
|
||||
}
|
||||
catch (StyletIoCFindConstructorException)
|
||||
{
|
||||
// If we can't resolve an auto-created type, that's fine
|
||||
// Don't remove it from the list of types - that way they'll get a
|
||||
// decent error message if they actually try and resolve it
|
||||
if (!registration.WasAutoCreated)
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public object Get(Type type, string key = null)
|
||||
{
|
||||
if (type == null)
|
||||
throw new ArgumentNullException("type");
|
||||
var generator = this.GetRegistrations(new TypeKey(type, key), false).GetSingle().GetGenerator();
|
||||
return generator();
|
||||
}
|
||||
|
||||
public T Get<T>(string key = null)
|
||||
{
|
||||
return (T)this.Get(typeof(T), key);
|
||||
}
|
||||
|
||||
public IEnumerable<object> GetAll(Type type, string key = null)
|
||||
{
|
||||
var typeKey = new TypeKey(type, key);
|
||||
IRegistration registration;
|
||||
if (!this.TryRetrieveGetAllRegistrationFromElementType(typeKey, null, out registration))
|
||||
throw new StyletIoCRegistrationException(String.Format("Could not find registration for type {0} and key '{1}'", typeKey.Type.Name));
|
||||
var generator = registration.GetGenerator();
|
||||
return (IEnumerable<object>)generator();
|
||||
}
|
||||
|
||||
public IEnumerable<T> GetAll<T>(string key = null)
|
||||
{
|
||||
return this.GetAll(typeof(T), key).Cast<T>();
|
||||
}
|
||||
|
||||
public object GetTypeOrAll(Type type, string key = null)
|
||||
{
|
||||
if (type == null)
|
||||
throw new ArgumentNullException("type");
|
||||
var generator = this.GetRegistrations(new TypeKey(type, key), true).GetSingle().GetGenerator();
|
||||
return generator();
|
||||
}
|
||||
|
||||
public T GetTypeOrAll<T>(string key = null)
|
||||
{
|
||||
return (T)this.GetTypeOrAll(typeof(T), key);
|
||||
}
|
||||
|
||||
public void BuildUp(object item)
|
||||
{
|
||||
var builderUpper = this.GetBuilderUpper(item.GetType());
|
||||
builderUpper.GetImplementor()(item);
|
||||
}
|
||||
|
||||
|
||||
internal bool CanResolve(TypeKey typeKey)
|
||||
{
|
||||
IRegistrationCollection registrations;
|
||||
|
||||
if (this.registrations.TryGetValue(typeKey, out registrations) ||
|
||||
this.TryCreateGenericTypesForUnboundGeneric(typeKey, out registrations))
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
// Is it a 'get all' request?
|
||||
IRegistration registration;
|
||||
return this.TryEnsureGetAllRegistrationCreated(typeKey, out registration);
|
||||
}
|
||||
|
||||
private Type GetElementTypeFromCollectionType(TypeKey typeKey)
|
||||
{
|
||||
Type type = typeKey.Type;
|
||||
// Elements are never removed from this.registrations, so we're safe to make this ContainsKey query
|
||||
if (!type.IsGenericType || type.GenericTypeArguments.Length != 1 || !this.registrations.ContainsKey(new TypeKey(type.GenericTypeArguments[0], typeKey.Key)))
|
||||
return null;
|
||||
return type.GenericTypeArguments[0];
|
||||
}
|
||||
|
||||
private bool TryRetrieveGetAllRegistrationFromElementType(TypeKey elementTypeKey, Type collectionTypeOrNull, out IRegistration registration)
|
||||
{
|
||||
// TryGet first, as making the generic type is expensive
|
||||
// If it isn't present, and can be made, GetOrAdd to try and add it, but return the now-existing registration if someone beat us to it
|
||||
if (this.getAllRegistrations.TryGetValue(elementTypeKey, out registration))
|
||||
return true;
|
||||
|
||||
var listType = typeof(List<>).MakeGenericType(elementTypeKey.Type);
|
||||
if (collectionTypeOrNull != null && !collectionTypeOrNull.IsAssignableFrom(listType))
|
||||
return false;
|
||||
|
||||
registration = this.getAllRegistrations.GetOrAdd(elementTypeKey, x => new GetAllRegistration(listType, this) { Key = elementTypeKey.Key });
|
||||
return true;
|
||||
}
|
||||
|
||||
// Returns the type of element if it's valid
|
||||
private bool TryEnsureGetAllRegistrationCreated(TypeKey typeKey, out IRegistration registration)
|
||||
{
|
||||
registration = null;
|
||||
var elementType = this.GetElementTypeFromCollectionType(typeKey);
|
||||
if (elementType == null)
|
||||
return false;
|
||||
|
||||
return this.TryRetrieveGetAllRegistrationFromElementType(new TypeKey(elementType, typeKey.Key), typeKey.Type, out registration);
|
||||
}
|
||||
|
||||
private bool TryCreateGenericTypesForUnboundGeneric(TypeKey typeKey, out IRegistrationCollection registrations)
|
||||
{
|
||||
registrations = null;
|
||||
var type = typeKey.Type;
|
||||
|
||||
if (!type.IsGenericType || type.GenericTypeArguments.Length == 0)
|
||||
return false;
|
||||
|
||||
Type unboundGenericType = type.GetGenericTypeDefinition();
|
||||
|
||||
List<UnboundGeneric> unboundGenerics;
|
||||
if (!this.unboundGenerics.TryGetValue(new TypeKey(unboundGenericType, typeKey.Key), out unboundGenerics))
|
||||
return false;
|
||||
|
||||
// Need to lock this, as someone might modify the underying list by registering a new unbound generic
|
||||
lock (unboundGenerics)
|
||||
{
|
||||
foreach (var unboundGeneric in unboundGenerics)
|
||||
{
|
||||
if (unboundGeneric == null)
|
||||
continue;
|
||||
|
||||
// Consider this scenario:
|
||||
// interface IC<T, U> { } class C<T, U> : IC<U, T> { }
|
||||
// Then they ask for an IC<int, bool>. We need to give them a C<bool, int>
|
||||
// Search the ancestry of C for an IC (called implOfUnboundGenericType), then create a mapping which says that
|
||||
// U is a bool and T is an int by comparing this against 'type' - the IC<T, U> that's registered as the service
|
||||
// Then use this when making the type for C
|
||||
|
||||
Type newType;
|
||||
if (unboundGeneric.Type == unboundGenericType)
|
||||
{
|
||||
newType = type;
|
||||
}
|
||||
else
|
||||
{
|
||||
var implOfUnboundGenericType = unboundGeneric.Type.GetBaseTypesAndInterfaces().Single(x => x.Name == unboundGenericType.Name);
|
||||
var mapping = implOfUnboundGenericType.GenericTypeArguments.Zip(type.GenericTypeArguments, (n, t) => new { Type = t, Name = n });
|
||||
|
||||
newType = unboundGeneric.Type.MakeGenericType(unboundGeneric.Type.GetTypeInfo().GenericTypeParameters.Select(x => mapping.Single(t => t.Name.Name == x.Name).Type).ToArray());
|
||||
}
|
||||
|
||||
if (!type.IsAssignableFrom(newType))
|
||||
continue;
|
||||
|
||||
// Right! We've made a new generic type we can use
|
||||
var registration = unboundGeneric.CreateRegistrationForType(newType);
|
||||
|
||||
// AddRegistration returns the IRegistrationCollection which was added/updated, so the one returned from the final
|
||||
// call to AddRegistration is the final IRegistrationCollection for this key
|
||||
registrations = this.AddRegistration(typeKey, registration);
|
||||
}
|
||||
}
|
||||
|
||||
return registrations != null;
|
||||
}
|
||||
|
||||
internal Expression GetExpression(TypeKey typeKey, bool searchGetAllTypes)
|
||||
{
|
||||
return this.GetRegistrations(typeKey, searchGetAllTypes).GetSingle().GetInstanceExpression();
|
||||
}
|
||||
|
||||
internal IRegistrationCollection GetRegistrations(TypeKey typeKey, bool searchGetAllTypes)
|
||||
{
|
||||
IRegistrationCollection registrations;
|
||||
|
||||
// Try to get registrations. If there are none, see if we can add some from unbound generics
|
||||
if (!this.registrations.TryGetValue(typeKey, out registrations) &&
|
||||
!this.TryCreateGenericTypesForUnboundGeneric(typeKey, out registrations))
|
||||
{
|
||||
if (searchGetAllTypes)
|
||||
{
|
||||
// Couldn't find this type - is it a 'get all' collection type? (i.e. they've put IEnumerable<TypeWeCanResolve> in a ctor param)
|
||||
IRegistration registration;
|
||||
if (!this.TryEnsureGetAllRegistrationCreated(typeKey, out registration))
|
||||
throw new StyletIoCRegistrationException(String.Format("No registrations found for service {0}.", typeKey.Type.Name));
|
||||
|
||||
// Got this far? Good. There's actually a 'get all' collection type. Proceed with that
|
||||
registrations = new SingleRegistration(registration);
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new StyletIoCRegistrationException(String.Format("No registrations found for service {0}.", typeKey.Type.Name));
|
||||
}
|
||||
}
|
||||
|
||||
return registrations;
|
||||
}
|
||||
|
||||
internal IRegistrationCollection AddRegistration(TypeKey typeKey, IRegistration registration)
|
||||
{
|
||||
return this.registrations.AddOrUpdate(typeKey, x => new SingleRegistration(registration), (x, c) => c.AddRegistration(registration));
|
||||
}
|
||||
|
||||
internal void AddUnboundGeneric(TypeKey typeKey, UnboundGeneric unboundGeneric)
|
||||
{
|
||||
// We're not worried about thread-safety across multiple calls to this function (as it's only called as part of setup, which we're
|
||||
// not thread-safe about). However someone might be fetching something from this list while we're modifying it, which we need to avoid
|
||||
var unboundGenerics = this.unboundGenerics.GetOrAdd(typeKey, x => new List<UnboundGeneric>());
|
||||
lock (unboundGenerics)
|
||||
{
|
||||
// Is there an auto-registration for this type? If so, remove it
|
||||
var existingEntry = unboundGenerics.Where(x => x.Type == unboundGeneric.Type).FirstOrDefault();
|
||||
if (existingEntry != null)
|
||||
{
|
||||
if (existingEntry.WasAutoCreated)
|
||||
unboundGenerics.Remove(existingEntry);
|
||||
else
|
||||
throw new StyletIoCRegistrationException(String.Format("Multiple registrations for type {0} found", typeKey.Type.Name));
|
||||
}
|
||||
|
||||
unboundGenerics.Add(unboundGeneric);
|
||||
}
|
||||
}
|
||||
|
||||
internal Type GetFactoryForType(Type serviceType)
|
||||
{
|
||||
if (!serviceType.IsInterface)
|
||||
throw new StyletIoCCreateFactoryException(String.Format("Unable to create a factory implementing type {0}, as it isn't an interface", serviceType.Name));
|
||||
|
||||
// Have we built it already?
|
||||
Type factoryType;
|
||||
if (this.factories.TryGetValue(serviceType, out factoryType))
|
||||
return factoryType;
|
||||
|
||||
if (this.factoryBuilder == null)
|
||||
{
|
||||
var assemblyName = new AssemblyName(FactoryAssemblyName);
|
||||
var assemblyBuilder = AppDomain.CurrentDomain.DefineDynamicAssembly(assemblyName, AssemblyBuilderAccess.Run);
|
||||
var moduleBuilder = assemblyBuilder.DefineDynamicModule("StyletIoCFactoryModule");
|
||||
Interlocked.CompareExchange(ref this.factoryBuilder, moduleBuilder, null);
|
||||
}
|
||||
|
||||
// If the service is 'ISomethingFactory', call out new class 'SomethingFactory'
|
||||
var typeBuilder = this.factoryBuilder.DefineType(serviceType.Name.Substring(1), TypeAttributes.Public);
|
||||
typeBuilder.AddInterfaceImplementation(serviceType);
|
||||
|
||||
// Define a field which holds a reference to this ioc container
|
||||
var containerField = typeBuilder.DefineField("container", typeof(IContainer), FieldAttributes.Private);
|
||||
|
||||
// Add a constructor which takes one argument - the container - and sets the field
|
||||
// public Name(IContainer container)
|
||||
// {
|
||||
// this.container = container;
|
||||
// }
|
||||
var ctorBuilder = typeBuilder.DefineConstructor(MethodAttributes.Public, CallingConventions.Standard, new Type[] { typeof(IContainer) });
|
||||
var ilGenerator = ctorBuilder.GetILGenerator();
|
||||
// Load 'this' and the IOC container onto the stack
|
||||
ilGenerator.Emit(OpCodes.Ldarg_0);
|
||||
ilGenerator.Emit(OpCodes.Ldarg_1);
|
||||
// Store the IOC container in this.container
|
||||
ilGenerator.Emit(OpCodes.Stfld, containerField);
|
||||
ilGenerator.Emit(OpCodes.Ret);
|
||||
|
||||
// These are needed by all methods, so get them now
|
||||
// IContainer.GetTypeOrAll(Type, string)
|
||||
var containerGetMethod = typeof(IContainer).GetMethod("GetTypeOrAll", new Type[] { typeof(Type), typeof(string) });
|
||||
// Type.GetTypeFromHandler(RuntimeTypeHandle)
|
||||
var typeFromHandleMethod = typeof(Type).GetMethod("GetTypeFromHandle");
|
||||
|
||||
// Go through each method, emmitting an implementation for each
|
||||
foreach (var methodInfo in serviceType.GetMethods())
|
||||
{
|
||||
var parameters = methodInfo.GetParameters();
|
||||
if (!(parameters.Length == 0 || (parameters.Length == 1 && parameters[0].ParameterType == typeof(string))))
|
||||
throw new StyletIoCCreateFactoryException("Can only implement methods with zero arguments, or a single string argument");
|
||||
|
||||
if (methodInfo.ReturnType == typeof(void))
|
||||
throw new StyletIoCCreateFactoryException("Can only implement methods which return something");
|
||||
|
||||
var methodBuilder = typeBuilder.DefineMethod(methodInfo.Name, MethodAttributes.Public | MethodAttributes.Virtual, methodInfo.ReturnType, parameters.Select(x => x.ParameterType).ToArray());
|
||||
var methodIlGenerator = methodBuilder.GetILGenerator();
|
||||
// Load 'this' onto stack
|
||||
// Stack: [this]
|
||||
methodIlGenerator.Emit(OpCodes.Ldarg_0);
|
||||
// Load value of 'container' field of 'this' onto stack
|
||||
// Stack: [this.container]
|
||||
methodIlGenerator.Emit(OpCodes.Ldfld, containerField);
|
||||
// New local variable which represents type to load
|
||||
LocalBuilder lb = methodIlGenerator.DeclareLocal(methodInfo.ReturnType);
|
||||
// Load this onto the stack. This is a RuntimeTypeHandle
|
||||
// Stack: [this.container, runtimeTypeHandleOfReturnType]
|
||||
methodIlGenerator.Emit(OpCodes.Ldtoken, lb.LocalType);
|
||||
// Invoke Type.GetTypeFromHandle with this
|
||||
// This is equivalent to calling typeof(T)
|
||||
// Stack: [this.container, typeof(returnType)]
|
||||
methodIlGenerator.Emit(OpCodes.Call, typeFromHandleMethod);
|
||||
// Load the given key (if it's a parameter), or null if it isn't, onto the stack
|
||||
// Stack: [this.container, typeof(returnType), key]
|
||||
if (parameters.Length == 0)
|
||||
methodIlGenerator.Emit(OpCodes.Ldnull); // Load null as the key
|
||||
else
|
||||
methodIlGenerator.Emit(OpCodes.Ldarg_1); // Load the given string as the key
|
||||
// Call container.Get(type, key)
|
||||
// Stack: [returnedInstance]
|
||||
methodIlGenerator.Emit(OpCodes.Callvirt, containerGetMethod);
|
||||
methodIlGenerator.Emit(OpCodes.Ret);
|
||||
|
||||
typeBuilder.DefineMethodOverride(methodBuilder, methodInfo);
|
||||
}
|
||||
|
||||
Type constructedType;
|
||||
try
|
||||
{
|
||||
constructedType = typeBuilder.CreateType();
|
||||
}
|
||||
catch (TypeLoadException e)
|
||||
{
|
||||
throw new StyletIoCCreateFactoryException(String.Format("Unable to create factory type for interface {0}. Ensure that the interface is public, or add [assembly: InternalsVisibleTo(StyletIoC.FactoryAssemblyName)] to your AssemblyInfo.cs", serviceType.Name), e);
|
||||
}
|
||||
var actualType = this.factories.GetOrAdd(serviceType, constructedType);
|
||||
return actualType;
|
||||
}
|
||||
|
||||
internal BuilderUpper GetBuilderUpper(Type type)
|
||||
{
|
||||
return this.builderUppers.GetOrAdd(type, x => new BuilderUpper(type, this));
|
||||
}
|
||||
}
|
||||
|
||||
internal class TypeKey
|
||||
{
|
||||
public readonly Type Type;
|
||||
public readonly string Key;
|
||||
|
||||
public TypeKey(Type type, string key)
|
||||
{
|
||||
this.Type = type;
|
||||
this.Key = key;
|
||||
}
|
||||
|
||||
public override int GetHashCode()
|
||||
{
|
||||
if (this.Key == null)
|
||||
return this.Type.GetHashCode();
|
||||
return this.Type.GetHashCode() ^ this.Key.GetHashCode();
|
||||
}
|
||||
|
||||
public override bool Equals(object obj)
|
||||
{
|
||||
if (!(obj is TypeKey))
|
||||
return false;
|
||||
var other = (TypeKey)obj;
|
||||
return other.Type == this.Type && other.Key == this.Key;
|
||||
}
|
||||
}
|
||||
|
||||
internal static class TypeExtensions
|
||||
{
|
||||
public static IEnumerable<Type> GetBaseTypesAndInterfaces(this Type type)
|
||||
{
|
||||
return type.GetInterfaces().Concat(type.GetBaseTypes());
|
||||
}
|
||||
|
||||
public static IEnumerable<Type> GetBaseTypes(this Type type)
|
||||
{
|
||||
if (type == typeof(object))
|
||||
yield break;
|
||||
var baseType = type.BaseType ?? typeof(object);
|
||||
|
||||
while (baseType != null)
|
||||
{
|
||||
yield return baseType;
|
||||
baseType = baseType.BaseType;
|
||||
}
|
||||
}
|
||||
|
||||
public static bool Implements(this Type implementationType, Type serviceType)
|
||||
{
|
||||
return serviceType.IsAssignableFrom(implementationType) ||
|
||||
implementationType.GetBaseTypesAndInterfaces().Any(x => x == serviceType || (x.IsGenericType && x.GetGenericTypeDefinition() == serviceType));
|
||||
}
|
||||
}
|
||||
|
||||
public interface IInjectionAware
|
||||
{
|
||||
void ParametersInjected();
|
||||
}
|
||||
|
||||
public class StyletIoCException : Exception
|
||||
{
|
||||
public StyletIoCException(string message) : base(message) { }
|
||||
public StyletIoCException(string message, Exception innerException) : base(message, innerException) { }
|
||||
}
|
||||
|
||||
public class StyletIoCRegistrationException : StyletIoCException
|
||||
{
|
||||
public StyletIoCRegistrationException(string message) : base(message) { }
|
||||
public StyletIoCRegistrationException(string message, Exception innerException) : base(message, innerException) { }
|
||||
}
|
||||
|
||||
public class StyletIoCFindConstructorException : StyletIoCException
|
||||
{
|
||||
public StyletIoCFindConstructorException(string message) : base(message) { }
|
||||
public StyletIoCFindConstructorException(string message, Exception innerException) : base(message, innerException) { }
|
||||
}
|
||||
|
||||
public class StyletIoCCreateFactoryException : StyletIoCException
|
||||
{
|
||||
public StyletIoCCreateFactoryException(string message) : base(message) { }
|
||||
public StyletIoCCreateFactoryException(string message, Exception innerException) : base(message, innerException) { }
|
||||
}
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Constructor | AttributeTargets.Parameter | AttributeTargets.Field | AttributeTargets.Property, Inherited = false, AllowMultiple = false)]
|
||||
public sealed class InjectAttribute : Attribute
|
||||
{
|
||||
public InjectAttribute()
|
||||
{
|
||||
}
|
||||
|
||||
public InjectAttribute(string key)
|
||||
{
|
||||
this.Key = key;
|
||||
}
|
||||
|
||||
// This is a named argument
|
||||
public string Key { get; set; }
|
||||
}
|
||||
}
|
|
@ -0,0 +1,36 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Reflection;
|
||||
|
||||
namespace StyletIoC
|
||||
{
|
||||
internal class UnboundGeneric
|
||||
{
|
||||
private StyletIoCContainer container;
|
||||
public bool WasAutoCreated { get; set; }
|
||||
public string Key { get; set; }
|
||||
public Type Type { get; private set; }
|
||||
public int NumTypeParams
|
||||
{
|
||||
get { return this.Type.GetTypeInfo().GenericTypeParameters.Length; }
|
||||
}
|
||||
public bool IsSingleton { get; private set; }
|
||||
|
||||
public UnboundGeneric(Type type, StyletIoCContainer container, bool isSingleton)
|
||||
{
|
||||
this.Type = type;
|
||||
this.container = container;
|
||||
}
|
||||
|
||||
public IRegistration CreateRegistrationForType(Type boundType)
|
||||
{
|
||||
if (this.IsSingleton)
|
||||
return new SingletonRegistration(new TypeCreator(boundType, this.container)) { WasAutoCreated = this.WasAutoCreated };
|
||||
else
|
||||
return new TransientRegistration(new TypeCreator(boundType, this.container)) { WasAutoCreated = this.WasAutoCreated };
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
using NUnit.Framework;
|
||||
using Stylet;
|
||||
using StyletIoC;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
@ -23,7 +23,7 @@ namespace StyletUnitTests
|
|||
[Test]
|
||||
public void NongenericInterfaceToAllImplementations()
|
||||
{
|
||||
var ioc = new StyletIoC();
|
||||
var ioc = new StyletIoCContainer();
|
||||
ioc.Bind<I1>().ToAllImplementations();
|
||||
|
||||
var result = ioc.GetAll<I1>().ToList();
|
||||
|
@ -35,7 +35,7 @@ namespace StyletUnitTests
|
|||
[Test]
|
||||
public void GenericInterfaceToAllImplementations()
|
||||
{
|
||||
var ioc = new StyletIoC();
|
||||
var ioc = new StyletIoCContainer();
|
||||
ioc.Bind(typeof(I2<>)).ToAllImplementations();
|
||||
|
||||
var result = ioc.GetAll<I2<int>>().ToList();
|
||||
|
@ -47,7 +47,7 @@ namespace StyletUnitTests
|
|||
[Test]
|
||||
public void IgnoresAllImplementsWhichIsNotPossible()
|
||||
{
|
||||
var ioc = new StyletIoC();
|
||||
var ioc = new StyletIoCContainer();
|
||||
ioc.Bind<I1>().ToAllImplementations();
|
||||
|
||||
var result = ioc.GetAll<I1>().ToList();
|
|
@ -1,5 +1,5 @@
|
|||
using NUnit.Framework;
|
||||
using Stylet;
|
||||
using StyletIoC;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
@ -25,14 +25,14 @@ namespace StyletUnitTests
|
|||
[Test]
|
||||
public void ThrowsIfTypeDoesNotImplementService()
|
||||
{
|
||||
var ioc = new StyletIoC();
|
||||
var ioc = new StyletIoCContainer();
|
||||
Assert.Throws<StyletIoCRegistrationException>(() =>ioc.Bind<I1>().To<C2>());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ThrowsIfImplementationIsNotConcrete()
|
||||
{
|
||||
var ioc = new StyletIoC();
|
||||
var ioc = new StyletIoCContainer();
|
||||
Assert.Throws<StyletIoCRegistrationException>(() => ioc.Bind<I1>().To<I3>());
|
||||
Assert.Throws<StyletIoCRegistrationException>(() => ioc.Bind<I1>().To<C4>());
|
||||
}
|
||||
|
@ -40,28 +40,28 @@ namespace StyletUnitTests
|
|||
[Test]
|
||||
public void ThrowsIfImplementationIsSingletonUnboundGeneric()
|
||||
{
|
||||
var ioc = new StyletIoC();
|
||||
var ioc = new StyletIoCContainer();
|
||||
Assert.Throws<StyletIoCRegistrationException>(() => ioc.BindSingleton<I1>().To(typeof(C5<>)));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ThrowsIfUnboundGenericServiceBoundToNormalImplementation()
|
||||
{
|
||||
var ioc = new StyletIoC();
|
||||
var ioc = new StyletIoCContainer();
|
||||
Assert.Throws<StyletIoCRegistrationException>(() => ioc.Bind(typeof(I6<>)).To<C6<int>>());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ThrowsIfNormalServiceBoundToUnboundGenericService()
|
||||
{
|
||||
var ioc = new StyletIoC();
|
||||
var ioc = new StyletIoCContainer();
|
||||
Assert.Throws<StyletIoCRegistrationException>(() => ioc.Bind<I6<int>>().To(typeof(C6<>)));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ThrowsIfUnboundTypesHaveDifferentNumbersOfTypeParameters()
|
||||
{
|
||||
var ioc = new StyletIoC();
|
||||
var ioc = new StyletIoCContainer();
|
||||
Assert.Throws<StyletIoCRegistrationException>(() => ioc.Bind(typeof(I6<>)).To(typeof(C7<,>)));
|
||||
Assert.Throws<StyletIoCRegistrationException>(() => ioc.Bind(typeof(I7<,>)).To(typeof(C6<>)));
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
using NUnit.Framework;
|
||||
using Stylet;
|
||||
using StyletIoC;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
@ -99,7 +99,7 @@ namespace StyletUnitTests
|
|||
[Test]
|
||||
public void RecursivelyPopulatesConstructorParams()
|
||||
{
|
||||
var ioc = new StyletIoC();
|
||||
var ioc = new StyletIoCContainer();
|
||||
ioc.Bind<C1>().ToSelf();
|
||||
ioc.Bind<C2>().ToSelf();
|
||||
ioc.Bind<C3>().ToSelf();
|
||||
|
@ -115,7 +115,7 @@ namespace StyletUnitTests
|
|||
[Test]
|
||||
public void UsesConstructorParamKeys()
|
||||
{
|
||||
var ioc = new StyletIoC();
|
||||
var ioc = new StyletIoCContainer();
|
||||
ioc.Bind<C1>().ToSelf("key1");
|
||||
ioc.Bind<C4>().ToSelf();
|
||||
|
||||
|
@ -127,7 +127,7 @@ namespace StyletUnitTests
|
|||
[Test]
|
||||
public void ThrowsIfConstructorParamKeyNotRegistered()
|
||||
{
|
||||
var ioc = new StyletIoC();
|
||||
var ioc = new StyletIoCContainer();
|
||||
ioc.Bind<C4>().ToSelf();
|
||||
ioc.Bind<C1>().ToSelf();
|
||||
|
||||
|
@ -137,7 +137,7 @@ namespace StyletUnitTests
|
|||
[Test]
|
||||
public void ChoosesCtorWithMostParamsWeCanFulfill()
|
||||
{
|
||||
var ioc = new StyletIoC();
|
||||
var ioc = new StyletIoCContainer();
|
||||
ioc.Bind<C1>().ToSelf();
|
||||
ioc.Bind<C2>().ToSelf();
|
||||
ioc.Bind<C5>().ToSelf();
|
||||
|
@ -149,7 +149,7 @@ namespace StyletUnitTests
|
|||
[Test]
|
||||
public void ChoosesCtorWithAttribute()
|
||||
{
|
||||
var ioc = new StyletIoC();
|
||||
var ioc = new StyletIoCContainer();
|
||||
ioc.Bind<C1>().ToSelf();
|
||||
ioc.Bind<C2>().ToSelf();
|
||||
ioc.Bind<C6>().ToSelf();
|
||||
|
@ -161,7 +161,7 @@ namespace StyletUnitTests
|
|||
[Test]
|
||||
public void ThrowsIfMoreThanOneCtorWithAttribute()
|
||||
{
|
||||
var ioc = new StyletIoC();
|
||||
var ioc = new StyletIoCContainer();
|
||||
ioc.Bind<C1>().ToSelf();
|
||||
ioc.Bind<C7>().ToSelf();
|
||||
|
||||
|
@ -171,7 +171,7 @@ namespace StyletUnitTests
|
|||
[Test]
|
||||
public void ThrowsIfNoCtorAvailable()
|
||||
{
|
||||
var ioc = new StyletIoC();
|
||||
var ioc = new StyletIoCContainer();
|
||||
ioc.Bind<C5>().ToSelf();
|
||||
|
||||
Assert.Throws<StyletIoCFindConstructorException>(() => ioc.Get<C5>());
|
||||
|
@ -180,7 +180,7 @@ namespace StyletUnitTests
|
|||
[Test]
|
||||
public void SingletonActuallySingleton()
|
||||
{
|
||||
var ioc = new StyletIoC();
|
||||
var ioc = new StyletIoCContainer();
|
||||
ioc.BindSingleton<C1>().ToSelf();
|
||||
ioc.Bind<C2>().ToSelf();
|
||||
ioc.Bind<C3>().ToSelf();
|
||||
|
@ -193,7 +193,7 @@ namespace StyletUnitTests
|
|||
[Test]
|
||||
public void IEnumerableHasAllInjected()
|
||||
{
|
||||
var ioc = new StyletIoC();
|
||||
var ioc = new StyletIoCContainer();
|
||||
ioc.Bind<C1>().To<C1>();
|
||||
ioc.Bind<I1>().To<C1>();
|
||||
ioc.Bind<I1>().To<C2>();
|
|
@ -1,5 +1,5 @@
|
|||
using NUnit.Framework;
|
||||
using Stylet;
|
||||
using StyletIoC;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
@ -13,6 +13,7 @@ namespace StyletUnitTests
|
|||
{
|
||||
public interface I1 { }
|
||||
public class C1 : I1 { }
|
||||
public class C12 : I1 { }
|
||||
|
||||
public interface I1Factory
|
||||
{
|
||||
|
@ -24,6 +25,11 @@ namespace StyletUnitTests
|
|||
I1 GetI1(string key = null);
|
||||
}
|
||||
|
||||
public interface I1Factory3
|
||||
{
|
||||
IEnumerable<I1> GetAllI1s();
|
||||
}
|
||||
|
||||
interface IPrivateFactory
|
||||
{
|
||||
}
|
||||
|
@ -41,7 +47,7 @@ namespace StyletUnitTests
|
|||
[Test]
|
||||
public void CreatesImplementationWithoutKey()
|
||||
{
|
||||
var ioc = new StyletIoC();
|
||||
var ioc = new StyletIoCContainer();
|
||||
ioc.Bind<I1>().To<C1>();
|
||||
ioc.Bind<I1Factory>().ToAbstractFactory();
|
||||
|
||||
|
@ -53,7 +59,7 @@ namespace StyletUnitTests
|
|||
[Test]
|
||||
public void CreatesImplementationWithKey()
|
||||
{
|
||||
var ioc = new StyletIoC();
|
||||
var ioc = new StyletIoCContainer();
|
||||
ioc.Bind<I1>().To<C1>("key");
|
||||
ioc.Bind<I1Factory2>().ToAbstractFactory();
|
||||
|
||||
|
@ -62,31 +68,47 @@ namespace StyletUnitTests
|
|||
Assert.IsInstanceOf<C1>(result);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void CreatesAllImplementations()
|
||||
{
|
||||
var ioc = new StyletIoCContainer();
|
||||
ioc.Bind<I1>().To<C1>();
|
||||
ioc.Bind<I1>().To<C12>();
|
||||
ioc.Bind<I1Factory3>().ToAbstractFactory();
|
||||
|
||||
var factory = ioc.Get<I1Factory3>();
|
||||
var results = factory.GetAllI1s().ToList();
|
||||
|
||||
Assert.AreEqual(2, results.Count);
|
||||
Assert.IsInstanceOf<C1>(results[0]);
|
||||
Assert.IsInstanceOf<C12>(results[1]);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ThrowsIfServiceTypeIsNotInterface()
|
||||
{
|
||||
var ioc = new StyletIoC();
|
||||
var ioc = new StyletIoCContainer();
|
||||
Assert.Throws<StyletIoCCreateFactoryException>(() => ioc.Bind<C1>().ToAbstractFactory());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ThrowsIfInterfaceNotPublic()
|
||||
{
|
||||
var ioc = new StyletIoC();
|
||||
var ioc = new StyletIoCContainer();
|
||||
Assert.Throws<StyletIoCCreateFactoryException>(() => ioc.Bind<IPrivateFactory>().ToAbstractFactory());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ThrowsIfMethodHasArgumentOtherThanString()
|
||||
{
|
||||
var ioc = new StyletIoC();
|
||||
var ioc = new StyletIoCContainer();
|
||||
Assert.Throws<StyletIoCCreateFactoryException>(() => ioc.Bind<IFactoryWithBadMethod>().ToAbstractFactory());
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ThrowsIfMethodReturningVoid()
|
||||
{
|
||||
var ioc = new StyletIoC();
|
||||
var ioc = new StyletIoCContainer();
|
||||
Assert.Throws<StyletIoCCreateFactoryException>(() => ioc.Bind<IFactoryWithVoidMethod>().ToAbstractFactory());
|
||||
}
|
||||
}
|
|
@ -1,5 +1,5 @@
|
|||
using NUnit.Framework;
|
||||
using Stylet;
|
||||
using StyletIoC;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
@ -25,7 +25,7 @@ namespace StyletUnitTests
|
|||
[Test]
|
||||
public void ImplementationTransientBindingsResolveGeneric()
|
||||
{
|
||||
var ioc = new StyletIoC();
|
||||
var ioc = new StyletIoCContainer();
|
||||
ioc.Bind<IC1>().To<C11>();
|
||||
ioc.Bind<IC1>().To<C12>();
|
||||
ioc.Bind<IC1>().To<C13>();
|
||||
|
@ -46,7 +46,7 @@ namespace StyletUnitTests
|
|||
[Test]
|
||||
public void ImplementationTransientBindingsResolveTyped()
|
||||
{
|
||||
var ioc = new StyletIoC();
|
||||
var ioc = new StyletIoCContainer();
|
||||
ioc.Bind(typeof(IC1)).To(typeof(C11));
|
||||
ioc.Bind(typeof(IC1)).To(typeof(C12));
|
||||
ioc.Bind(typeof(IC1)).To(typeof(C13));
|
||||
|
@ -66,7 +66,7 @@ namespace StyletUnitTests
|
|||
[Test]
|
||||
public void SingletonBindingsResolveGeneric()
|
||||
{
|
||||
var ioc = new StyletIoC();
|
||||
var ioc = new StyletIoCContainer();
|
||||
ioc.BindSingleton<IC1>().To<C11>();
|
||||
ioc.BindSingleton<IC1>().To<C12>();
|
||||
ioc.BindSingleton<IC1>().To<C13>();
|
||||
|
@ -86,7 +86,7 @@ namespace StyletUnitTests
|
|||
[Test]
|
||||
public void SingletonBindingsResolveTyped()
|
||||
{
|
||||
var ioc = new StyletIoC();
|
||||
var ioc = new StyletIoCContainer();
|
||||
ioc.BindSingleton(typeof(IC1)).To(typeof(C11));
|
||||
ioc.BindSingleton(typeof(IC1)).To(typeof(C12));
|
||||
ioc.BindSingleton(typeof(IC1)).To(typeof(C13));
|
|
@ -1,5 +1,5 @@
|
|||
using NUnit.Framework;
|
||||
using Stylet;
|
||||
using StyletIoC;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
@ -22,7 +22,7 @@ namespace StyletUnitTests
|
|||
[Test]
|
||||
public void GetReturnsKeyedType()
|
||||
{
|
||||
var ioc = new StyletIoC();
|
||||
var ioc = new StyletIoCContainer();
|
||||
ioc.Bind<IC>().To<C1>("key1");
|
||||
ioc.Bind<IC>().To<C2>("key2");
|
||||
|
||||
|
@ -33,7 +33,7 @@ namespace StyletUnitTests
|
|||
[Test]
|
||||
public void GetAllReturnsKeyedTypes()
|
||||
{
|
||||
var ioc = new StyletIoC();
|
||||
var ioc = new StyletIoCContainer();
|
||||
ioc.Bind<IC>().To<C1>("key1");
|
||||
ioc.Bind<IC>().To<C2>("key1");
|
||||
ioc.Bind<IC>().To<C3>();
|
||||
|
@ -48,7 +48,7 @@ namespace StyletUnitTests
|
|||
[Test]
|
||||
public void AttributeIsUsed()
|
||||
{
|
||||
var ioc = new StyletIoC();
|
||||
var ioc = new StyletIoCContainer();
|
||||
ioc.Bind<IC>().To<C3>();
|
||||
ioc.Bind<IC>().To<C4>();
|
||||
|
||||
|
@ -58,7 +58,7 @@ namespace StyletUnitTests
|
|||
[Test]
|
||||
public void GivenKeyOverridesAttribute()
|
||||
{
|
||||
var ioc = new StyletIoC();
|
||||
var ioc = new StyletIoCContainer();
|
||||
ioc.Bind<IC>().To<C3>();
|
||||
ioc.Bind<IC>().To<C4>("key2");
|
||||
|
|
@ -1,5 +1,5 @@
|
|||
using NUnit.Framework;
|
||||
using Stylet;
|
||||
using StyletIoC;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
@ -17,7 +17,7 @@ namespace StyletUnitTests
|
|||
[Test]
|
||||
public void SelfTransientBindingResolvesGeneric()
|
||||
{
|
||||
var ioc = new StyletIoC();
|
||||
var ioc = new StyletIoCContainer();
|
||||
ioc.Bind<C1>().ToSelf();
|
||||
var obj1 = ioc.Get<C1>();
|
||||
var obj2 = ioc.Get<C1>();
|
||||
|
@ -29,7 +29,7 @@ namespace StyletUnitTests
|
|||
[Test]
|
||||
public void SelfTransientBindingResolvesTyped()
|
||||
{
|
||||
var ioc = new StyletIoC();
|
||||
var ioc = new StyletIoCContainer();
|
||||
ioc.Bind(typeof(C1)).ToSelf();
|
||||
var obj1 = ioc.Get(typeof(C1));
|
||||
var obj2 = ioc.Get(typeof(C1));
|
||||
|
@ -41,7 +41,7 @@ namespace StyletUnitTests
|
|||
[Test]
|
||||
public void SelfSingletonBindingResolvesGeneric()
|
||||
{
|
||||
var ioc = new StyletIoC();
|
||||
var ioc = new StyletIoCContainer();
|
||||
ioc.BindSingleton<C1>().ToSelf();
|
||||
var obj1 = ioc.Get<C1>();
|
||||
var obj2 = ioc.Get<C1>();
|
||||
|
@ -53,7 +53,7 @@ namespace StyletUnitTests
|
|||
[Test]
|
||||
public void SelfSingletonBindingResolvesTyped()
|
||||
{
|
||||
var ioc = new StyletIoC();
|
||||
var ioc = new StyletIoCContainer();
|
||||
ioc.BindSingleton(typeof(C1)).ToSelf();
|
||||
var obj1 = ioc.Get(typeof(C1));
|
||||
var obj2 = ioc.Get(typeof(C1));
|
||||
|
@ -65,7 +65,7 @@ namespace StyletUnitTests
|
|||
[Test]
|
||||
public void FactoryTransientBindingResolvesGeneric()
|
||||
{
|
||||
var ioc = new StyletIoC();
|
||||
var ioc = new StyletIoCContainer();
|
||||
ioc.Bind<C1>().ToFactory(c => new C1());
|
||||
var obj1 = ioc.Get<C1>();
|
||||
var obj2 = ioc.Get<C1>();
|
||||
|
@ -77,7 +77,7 @@ namespace StyletUnitTests
|
|||
[Test]
|
||||
public void FactoryTransientBindingResolvesTyped()
|
||||
{
|
||||
var ioc = new StyletIoC();
|
||||
var ioc = new StyletIoCContainer();
|
||||
ioc.Bind(typeof(C1)).ToFactory(c => new C1());
|
||||
var obj1 = ioc.Get(typeof(C1));
|
||||
var obj2 = ioc.Get(typeof(C1));
|
||||
|
@ -89,7 +89,7 @@ namespace StyletUnitTests
|
|||
[Test]
|
||||
public void FactorySingletonBindingResolvesGeneric()
|
||||
{
|
||||
var ioc = new StyletIoC();
|
||||
var ioc = new StyletIoCContainer();
|
||||
ioc.BindSingleton<C1>().ToFactory(c => new C1());
|
||||
var obj1 = ioc.Get<C1>();
|
||||
var obj2 = ioc.Get<C1>();
|
||||
|
@ -101,7 +101,7 @@ namespace StyletUnitTests
|
|||
[Test]
|
||||
public void FactorySingletonBindingResolvesTyped()
|
||||
{
|
||||
var ioc = new StyletIoC();
|
||||
var ioc = new StyletIoCContainer();
|
||||
ioc.BindSingleton(typeof(C1)).ToFactory(c => new C1());
|
||||
var obj1 = ioc.Get(typeof(C1));
|
||||
var obj2 = ioc.Get(typeof(C1));
|
||||
|
@ -113,7 +113,7 @@ namespace StyletUnitTests
|
|||
[Test]
|
||||
public void ImplementationTransientBindingResolvesGeneric()
|
||||
{
|
||||
var ioc = new StyletIoC();
|
||||
var ioc = new StyletIoCContainer();
|
||||
ioc.Bind<IC1>().To<C1>();
|
||||
var obj1 = ioc.Get<IC1>();
|
||||
var obj2 = ioc.Get<IC1>();
|
||||
|
@ -125,7 +125,7 @@ namespace StyletUnitTests
|
|||
[Test]
|
||||
public void ImplementationTransientBindingResolvesTyped()
|
||||
{
|
||||
var ioc = new StyletIoC();
|
||||
var ioc = new StyletIoCContainer();
|
||||
ioc.Bind(typeof(IC1)).To(typeof(C1));
|
||||
var obj1 = ioc.Get(typeof(IC1));
|
||||
var obj2 = ioc.Get(typeof(IC1));
|
||||
|
@ -137,7 +137,7 @@ namespace StyletUnitTests
|
|||
[Test]
|
||||
public void ImplementationSingletonBindingResolvesGeneric()
|
||||
{
|
||||
var ioc = new StyletIoC();
|
||||
var ioc = new StyletIoCContainer();
|
||||
ioc.BindSingleton<IC1>().To<C1>();
|
||||
var obj1 = ioc.Get<IC1>();
|
||||
var obj2 = ioc.Get<IC1>();
|
||||
|
@ -149,7 +149,7 @@ namespace StyletUnitTests
|
|||
[Test]
|
||||
public void ImplementationSingletonBindingResolvesTyped()
|
||||
{
|
||||
var ioc = new StyletIoC();
|
||||
var ioc = new StyletIoCContainer();
|
||||
ioc.BindSingleton(typeof(IC1)).To(typeof(C1));
|
||||
var obj1 = ioc.Get(typeof(IC1));
|
||||
var obj2 = ioc.Get(typeof(IC1));
|
|
@ -1,5 +1,5 @@
|
|||
using NUnit.Framework;
|
||||
using Stylet;
|
||||
using StyletIoC;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
@ -65,7 +65,7 @@ namespace StyletUnitTests
|
|||
[Test]
|
||||
public void BuildsUpPublicFields()
|
||||
{
|
||||
var ioc = new StyletIoC();
|
||||
var ioc = new StyletIoCContainer();
|
||||
ioc.Bind<C1>().ToSelf();
|
||||
var subject = new Subject1();
|
||||
ioc.BuildUp(subject);
|
||||
|
@ -77,7 +77,7 @@ namespace StyletUnitTests
|
|||
[Test]
|
||||
public void BuildsUpPrivateFields()
|
||||
{
|
||||
var ioc = new StyletIoC();
|
||||
var ioc = new StyletIoCContainer();
|
||||
ioc.Bind<C1>().ToSelf();
|
||||
var subject = new Subject2();
|
||||
ioc.BuildUp(subject);
|
||||
|
@ -88,7 +88,7 @@ namespace StyletUnitTests
|
|||
[Test]
|
||||
public void BuildsUpPublicProperties()
|
||||
{
|
||||
var ioc = new StyletIoC();
|
||||
var ioc = new StyletIoCContainer();
|
||||
ioc.Bind<C1>().ToSelf();
|
||||
var subject = new Subject3();
|
||||
ioc.BuildUp(subject);
|
||||
|
@ -99,7 +99,7 @@ namespace StyletUnitTests
|
|||
[Test]
|
||||
public void BuildsUpPrivateProperties()
|
||||
{
|
||||
var ioc = new StyletIoC();
|
||||
var ioc = new StyletIoCContainer();
|
||||
ioc.Bind<C1>().ToSelf();
|
||||
var subject = new Subject4();
|
||||
ioc.BuildUp(subject);
|
||||
|
@ -111,7 +111,7 @@ namespace StyletUnitTests
|
|||
[Test]
|
||||
public void RespectsKeys()
|
||||
{
|
||||
var ioc = new StyletIoC();
|
||||
var ioc = new StyletIoCContainer();
|
||||
ioc.Bind<C1>().ToSelf("key");
|
||||
var subject = new Subject5();
|
||||
ioc.BuildUp(subject);
|
||||
|
@ -122,7 +122,7 @@ namespace StyletUnitTests
|
|||
[Test]
|
||||
public void ThrowsIfCanNotResolve()
|
||||
{
|
||||
var ioc = new StyletIoC();
|
||||
var ioc = new StyletIoCContainer();
|
||||
var subject = new Subject1();
|
||||
Assert.Throws<StyletIoCRegistrationException>(() => ioc.BuildUp(subject));
|
||||
}
|
||||
|
@ -130,7 +130,7 @@ namespace StyletUnitTests
|
|||
[Test]
|
||||
public void BuildsUpParametersOfNewlyCreatedType()
|
||||
{
|
||||
var ioc = new StyletIoC();
|
||||
var ioc = new StyletIoCContainer();
|
||||
ioc.Bind<C1>().ToSelf();
|
||||
ioc.Bind<Subject1>().ToSelf();
|
||||
var subject = ioc.Get<Subject1>();
|
||||
|
@ -142,7 +142,7 @@ namespace StyletUnitTests
|
|||
[Test]
|
||||
public void CallsParametersInjectedAfterInjectingParameters()
|
||||
{
|
||||
var ioc = new StyletIoC();
|
||||
var ioc = new StyletIoCContainer();
|
||||
ioc.Bind<C1>().ToSelf();
|
||||
ioc.Bind<Subject6>().ToSelf();
|
||||
var subject = ioc.Get<Subject6>();
|
|
@ -1,12 +1,12 @@
|
|||
using NUnit.Framework;
|
||||
using Stylet;
|
||||
using StyletIoC;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace StyletUnitTests
|
||||
namespace StyletUnitTests.StyletIoC
|
||||
{
|
||||
[TestFixture]
|
||||
public class StyletIoCUnboundGenericTests
|
||||
|
@ -20,7 +20,7 @@ namespace StyletUnitTests
|
|||
[Test]
|
||||
public void ResolvesSingleGenericType()
|
||||
{
|
||||
var ioc = new StyletIoC();
|
||||
var ioc = new StyletIoCContainer();
|
||||
ioc.Bind(typeof(C1<>)).ToSelf();
|
||||
|
||||
Assert.DoesNotThrow(() => ioc.Get<C1<int>>());
|
||||
|
@ -29,7 +29,7 @@ namespace StyletUnitTests
|
|||
[Test]
|
||||
public void ResolvesGenericTypeFromInterface()
|
||||
{
|
||||
var ioc = new StyletIoC();
|
||||
var ioc = new StyletIoCContainer();
|
||||
ioc.Bind(typeof(I1<>)).To(typeof(C1<>));
|
||||
|
||||
var result = ioc.Get<I1<int>>();
|
||||
|
@ -39,7 +39,7 @@ namespace StyletUnitTests
|
|||
[Test]
|
||||
public void ResolvesGenericTypeWhenOrderOfTypeParamsChanged()
|
||||
{
|
||||
var ioc = new StyletIoC();
|
||||
var ioc = new StyletIoCContainer();
|
||||
ioc.Bind(typeof(I2<,>)).To(typeof(C2<,>));
|
||||
|
||||
var c2 = ioc.Get<I2<int, bool>>();
|
|
@ -46,15 +46,15 @@
|
|||
<ItemGroup>
|
||||
<Compile Include="BindableCollectionTests.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
<Compile Include="StyletIoCAutobindingTests.cs" />
|
||||
<Compile Include="StyletIoCBindingChecksTests.cs" />
|
||||
<Compile Include="StyletIoCParameterInjectionTests.cs" />
|
||||
<Compile Include="StyletIoCConstructorInjectionTests.cs" />
|
||||
<Compile Include="StyletIoCFactoryTests.cs" />
|
||||
<Compile Include="StyletIoCGetAllTests.cs" />
|
||||
<Compile Include="StyletIoCGetSingleKeyedTests.cs" />
|
||||
<Compile Include="StyletIoCGetSingleTests.cs" />
|
||||
<Compile Include="StyletIoCUnboundGenericTests.cs" />
|
||||
<Compile Include="StyletIoC\StyletIoCAutobindingTests.cs" />
|
||||
<Compile Include="StyletIoC\StyletIoCBindingChecksTests.cs" />
|
||||
<Compile Include="StyletIoC\StyletIoCParameterInjectionTests.cs" />
|
||||
<Compile Include="StyletIoC\StyletIoCConstructorInjectionTests.cs" />
|
||||
<Compile Include="StyletIoC\StyletIoCFactoryTests.cs" />
|
||||
<Compile Include="StyletIoC\StyletIoCGetAllTests.cs" />
|
||||
<Compile Include="StyletIoC\StyletIoCGetSingleKeyedTests.cs" />
|
||||
<Compile Include="StyletIoC\StyletIoCGetSingleTests.cs" />
|
||||
<Compile Include="StyletIoC\UnboundGenericTests.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Service Include="{82A7F48D-3B50-4B1E-B82E-3ADA8210C358}" />
|
||||
|
|
Loading…
Reference in New Issue