#region License
//
// Author: Nate Kohari <[email protected]>
// Copyright (c) 2007-2010, Enkari, Ltd.
//
// Dual-licensed under the Apache License, Version 2.0, and the Microsoft Public License (Ms-PL).
// See the file LICENSE.txt for details.
//
#endregion
#region Using Directives
using System;
using System.Reflection;
using Telerik.JustMock.AutoMock.Ninject.Components;
using Telerik.JustMock.AutoMock.Ninject.Infrastructure;
using Telerik.JustMock.AutoMock.Ninject.Injection;
using Telerik.JustMock.AutoMock.Ninject.Planning.Directives;
using Telerik.JustMock.AutoMock.Ninject.Selection;
#endregion
namespace Telerik.JustMock.AutoMock.Ninject.Planning.Strategies
{
/// <summary>
/// Adds directives to plans indicating which properties should be injected during activation.
/// </summary>
public class PropertyReflectionStrategy : NinjectComponent, IPlanningStrategy
{
/// <summary>
/// Gets the selector component.
/// </summary>
public ISelector Selector { get; private set; }
/// <summary>
/// Gets the injector factory component.
/// </summary>
public IInjectorFactory InjectorFactory { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="PropertyReflectionStrategy"/> class.
/// </summary>
/// <param name="selector">The selector component.</param>
/// <param name="injectorFactory">The injector factory component.</param>
public PropertyReflectionStrategy(ISelector selector, IInjectorFactory injectorFactory)
{
Ensure.ArgumentNotNull(selector, "selector");
Ensure.ArgumentNotNull(injectorFactory, "injectorFactory");
Selector = selector;
InjectorFactory = injectorFactory;
}
/// <summary>
/// Adds a <see cref="PropertyInjectionDirective"/> to the plan for each property
/// that should be injected.
/// </summary>
/// <param name="plan">The plan that is being generated.</param>
public void Execute(IPlan plan)
{
Ensure.ArgumentNotNull(plan, "plan");
foreach (PropertyInfo property in Selector.SelectPropertiesForInjection(plan.Type))
plan.Add(new PropertyInjectionDirective(property, InjectorFactory.Create(property)));
}
}
}
#region License
//
// Author: Nate Kohari <[email protected]>
// Copyright (c) 2007-2010, Enkari, Ltd.
//
// Dual-licensed under the Apache License, Version 2.0, and the Microsoft Public License (Ms-PL).
// See the file LICENSE.txt for details.
//
#endregion
#region Using Directives
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Telerik.JustMock.AutoMock.Ninject.Infrastructure;
using Telerik.JustMock.AutoMock.Ninject.Infrastructure.Introspection;
using Telerik.JustMock.AutoMock.Ninject.Infrastructure.Language;
using Telerik.JustMock.AutoMock.Ninject.Injection;
using Telerik.JustMock.AutoMock.Ninject.Parameters;
using Telerik.JustMock.AutoMock.Ninject.Planning.Directives;
using Telerik.JustMock.AutoMock.Ninject.Planning.Targets;
#endregion
namespace Telerik.JustMock.AutoMock.Ninject.Activation.Strategies
{
/// <summary>
/// Injects properties on an instance during activation.
/// </summary>
public class PropertyInjectionStrategy : ActivationStrategy
{
private const BindingFlags DefaultFlags = BindingFlags.Public | BindingFlags.Instance;
private BindingFlags Flags
{
get
{
#if !NO_LCG && !SILVERLIGHT
return Settings.InjectNonPublic ? (DefaultFlags | BindingFlags.NonPublic) : DefaultFlags;
#else
return DefaultFlags;
#endif
}
}
/// <summary>
/// Gets the injector factory component.
/// </summary>
public IInjectorFactory InjectorFactory { get; set; }
/// <summary>
/// Initializes a new instance of the <see cref="PropertyInjectionStrategy"/> class.
/// </summary>
/// <param name="injectorFactory">The injector factory component.</param>
public PropertyInjectionStrategy(IInjectorFactory injectorFactory)
{
this.InjectorFactory = injectorFactory;
}
/// <summary>
/// Injects values into the properties as described by <see cref="PropertyInjectionDirective"/>s
/// contained in the plan.
/// </summary>
/// <param name="context">The context.</param>
/// <param name="reference">A reference to the instance being activated.</param>
public override void Activate(IContext context, InstanceReference reference)
{
Ensure.ArgumentNotNull(context, "context");
Ensure.ArgumentNotNull(reference, "reference");
var propertyValues = context.Parameters.OfType<IPropertyValue>().ToList();
foreach (var directive in context.Plan.GetAll<PropertyInjectionDirective>())
{
object value = this.GetValue(context, directive.Target, propertyValues);
directive.Injector(reference.Instance, value);
}
this.AssignProperyOverrides(context, reference, propertyValues);
}
/// <summary>
/// Applies user supplied override values to instance properties.
/// </summary>
/// <param name="context">The context.</param>
/// <param name="reference">A reference to the instance being activated.</param>
/// <param name="propertyValues">The parameter override value accessors.</param>
private void AssignProperyOverrides(IContext context, InstanceReference reference, IList<IPropertyValue> propertyValues)
{
var properties = reference.Instance.GetType().GetProperties(this.Flags);
foreach (var propertyValue in propertyValues)
{
string propertyName = propertyValue.Name;
var propertyInfo = properties.FirstOrDefault(property => string.Equals(property.Name, propertyName, StringComparison.Ordinal));
if (propertyInfo == null)
{
throw new ActivationException(ExceptionFormatter.CouldNotResolvePropertyForValueInjection(context.Request, propertyName));
}
var target = new PropertyInjectionDirective(propertyInfo, this.InjectorFactory.Create(propertyInfo));
object value = this.GetValue(context, target.Target, propertyValues);
target.Injector(reference.Instance, value);
}
}
/// <summary>
/// Gets the value to inject into the specified target.
/// </summary>
/// <param name="context">The context.</param>
/// <param name="target">The target.</param>
/// <param name="allPropertyValues">all property values of the current request.</param>
/// <returns>The value to inject into the specified target.</returns>
private object GetValue(IContext context, ITarget target, IEnumerable<IPropertyValue> allPropertyValues)
{
Ensure.ArgumentNotNull(context, "context");
Ensure.ArgumentNotNull(target, "target");
var parameter = allPropertyValues.SingleOrDefault(p => p.Name == target.Name);
return parameter != null ? parameter.GetValue(context, target) : target.ResolveWithin(context);
}
}
}
#region License
//
// Author: Nate Kohari <[email protected]>
// Copyright (c) 2007-2010, Enkari, Ltd.
//
// Dual-licensed under the Apache License, Version 2.0, and the Microsoft Public License (Ms-PL).
// See the file LICENSE.txt for details.
//
#endregion
#region Using Directives
using System;
using System.Reflection;
using Telerik.JustMock.AutoMock.Ninject.Injection;
using Telerik.JustMock.AutoMock.Ninject.Planning.Targets;
#endregion
namespace Telerik.JustMock.AutoMock.Ninject.Planning.Directives
{
/// <summary>
/// Describes the injection of a property.
/// </summary>
public class PropertyInjectionDirective : IDirective
{
/// <summary>
/// Gets or sets the injector that will be triggered.
/// </summary>
public PropertyInjector Injector { get; private set; }
/// <summary>
/// Gets or sets the injection target for the directive.
/// </summary>
public ITarget Target { get; private set; }
/// <summary>
/// Initializes a new instance of the <see cref="PropertyInjectionDirective"/> class.
/// </summary>
/// <param name="member">The member the directive describes.</param>
/// <param name="injector">The injector that will be triggered.</param>
public PropertyInjectionDirective(PropertyInfo member, PropertyInjector injector)
{
Injector = injector;
Target = CreateTarget(member);
}
/// <summary>
/// Creates a target for the property.
/// </summary>
/// <param name="propertyInfo">The property.</param>
/// <returns>The target for the property.</returns>
protected virtual ITarget CreateTarget(PropertyInfo propertyInfo)
{
return new PropertyTarget(propertyInfo);
}
}
}