Reflector StyletIoC into multiple implementation files

This commit is contained in:
Antony Male 2014-02-18 13:12:39 +00:00
parent 374f5d9049
commit a73a5f65d9
19 changed files with 1237 additions and 1158 deletions

View File

@ -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" />

File diff suppressed because it is too large Load Diff

View File

@ -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;
}
}
}

View File

@ -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);
}
}
}

View File

@ -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;
}
}
}

View File

@ -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;
}
}
}
}

View File

@ -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);
}
}
}

View File

@ -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; }
}
}

View File

@ -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 };
}
}
}

View File

@ -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();

View File

@ -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<>)));
}

View File

@ -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>();

View File

@ -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());
}
}

View File

@ -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));

View File

@ -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");

View File

@ -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));

View File

@ -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>();

View File

@ -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>>();

View File

@ -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}" />