Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>I actual answered my own question. Ninject had everything I needed to do the job, just not out-of-the-box. After calling Bind() an instance of IBindingToSyntax is returned. It has a method called WithPropertyValue. This method takes a value or a callback. The callback has an instance of Ninject.Activation.IContext, which has a IKernel, which finally has the Get method. So... I can look at the type of the property named in WithPropertyValue, grab the property, determine the type and then have the callback Get an instance for the property type. Phew.</p> <p>Here is an extension class I wrote to help in populating my typed repository sets:</p> <pre><code>using System; using System.Linq.Expressions; using System.Reflection; using Ninject; using Ninject.Activation; using Ninject.Planning.Targets; using Ninject.Syntax; namespace NinjectExtensions { /// &lt;summary&gt; /// Provides extension methods for the BindingWithSyntax class. /// &lt;/summary&gt; public static class BindingWithSyntaxExtensions { /// &lt;summary&gt; /// Indicates that the specified property should be injected with the bound type of the property. /// &lt;/summary&gt; /// &lt;typeparam name="TBinding"&gt;The type of the object to set the property for.&lt;/typeparam&gt; /// &lt;param name="instance"&gt;Used to add additional information to a binding.&lt;/param&gt; /// &lt;param name="name"&gt;The name of the property.&lt;/param&gt; /// &lt;returns&gt;The instance that was passed in.&lt;/returns&gt; public static IBindingWithSyntax&lt;TBinding&gt; WithPropertyValue&lt;TBinding&gt;(this IBindingWithSyntax&lt;TBinding&gt; instance, string name) { if (instance == null) { throw new ArgumentNullException("instance"); } PropertyInfo propertyInfo = typeof(TBinding).GetProperty(name); if (propertyInfo == null) { throw new ArgumentException("There was not a public property with the given name.", "name"); } Func&lt;IContext, object&gt; callback = context =&gt; context.Kernel.Get(propertyInfo.PropertyType); return instance.WithPropertyValue(name, callback); } /// &lt;summary&gt; /// Indicates that the specified property should be injected with the bound type of the property. /// &lt;/summary&gt; /// &lt;typeparam name="TBinding"&gt;The type of the object to set the property for.&lt;/typeparam&gt; /// &lt;typeparam name="T"&gt;The type of the property.&lt;/typeparam&gt; /// &lt;param name="instance"&gt;Used to add additional information to a binding.&lt;/param&gt; /// &lt;param name="propertyGetter"&gt;An expression yielding the property to set the value to.&lt;/param&gt; /// &lt;returns&gt;The instance that was passed in.&lt;/returns&gt; public static IBindingWithSyntax&lt;TBinding&gt; WithPropertyValue&lt;TBinding, T&gt;(this IBindingWithSyntax&lt;TBinding&gt; instance, Expression&lt;Func&lt;TBinding, T&gt;&gt; propertyGetter) { if (instance == null) { throw new ArgumentNullException("instance"); } if (propertyGetter == null) { throw new ArgumentNullException("propertyGetter"); } PropertyInfo propertyInfo = getPropertyInfo(typeof(TBinding), propertyGetter); Func&lt;IContext, object&gt; callback = context =&gt; context.Kernel.Get&lt;T&gt;(); return instance.WithPropertyValue(propertyInfo.Name, callback); } /// &lt;summary&gt; /// Indicates that the specified property should be injected with the given value. /// &lt;/summary&gt; /// &lt;typeparam name="TBinding"&gt;The type of the object to set the property for.&lt;/typeparam&gt; /// &lt;typeparam name="T"&gt;The type of the property.&lt;/typeparam&gt; /// &lt;param name="instance"&gt;Used to add additional information to a binding.&lt;/param&gt; /// &lt;param name="propertyGetter"&gt;An expression yielding the property to set the value to.&lt;/param&gt; /// &lt;param name="value"&gt;The value to set the property to.&lt;/param&gt; /// &lt;returns&gt;The instance that was passed in.&lt;/returns&gt; public static IBindingWithSyntax&lt;TBinding&gt; WithPropertyValue&lt;TBinding, T&gt;(this IBindingWithSyntax&lt;TBinding&gt; instance, Expression&lt;Func&lt;TBinding, T&gt;&gt; propertyGetter, T value) { if (instance == null) { throw new ArgumentNullException("instance"); } if (propertyGetter == null) { throw new ArgumentNullException("propertyGetter"); } PropertyInfo propertyInfo = getPropertyInfo(typeof(TBinding), propertyGetter); return instance.WithPropertyValue(propertyInfo.Name, value); } /// &lt;summary&gt; /// Indicates that the specified property should be injected with the value returned by the callback. /// &lt;/summary&gt; /// &lt;typeparam name="TBinding"&gt;The type of the object to set the property for.&lt;/typeparam&gt; /// &lt;typeparam name="T"&gt;The type of the property.&lt;/typeparam&gt; /// &lt;param name="instance"&gt;Used to add additional information to a binding.&lt;/param&gt; /// &lt;param name="propertyGetter"&gt;An expression yielding the property to set the value to.&lt;/param&gt; /// &lt;param name="callback"&gt;A function to call to retrieve the value to set the property to.&lt;/param&gt; /// &lt;returns&gt;The instance that was passed in.&lt;/returns&gt; public static IBindingWithSyntax&lt;TBinding&gt; WithPropertyValue&lt;TBinding, T&gt;(this IBindingWithSyntax&lt;TBinding&gt; instance, Expression&lt;Func&lt;TBinding, T&gt;&gt; propertyGetter, Func&lt;IContext, T&gt; callback) { if (instance == null) { throw new ArgumentNullException("instance"); } if (propertyGetter == null) { throw new ArgumentNullException("propertyGetter"); } if (callback == null) { throw new ArgumentNullException("callback"); } PropertyInfo propertyInfo = getPropertyInfo(typeof(TBinding), propertyGetter); Func&lt;IContext, object&gt; baseCallback = context =&gt; callback(context); return instance.WithPropertyValue(propertyInfo.Name, baseCallback); } /// &lt;summary&gt; /// Indicates that the specified property should be injected with the value returned by the callback. /// &lt;/summary&gt; /// &lt;typeparam name="TBinding"&gt;The type of the object to set the property for.&lt;/typeparam&gt; /// &lt;typeparam name="T"&gt;The type of the property.&lt;/typeparam&gt; /// &lt;param name="instance"&gt;Used to add additional information to a binding.&lt;/param&gt; /// &lt;param name="propertyGetter"&gt;An expression yielding the property to set the value to.&lt;/param&gt; /// &lt;param name="callback"&gt;A function to call to retrieve the value to set the property to.&lt;/param&gt; /// &lt;returns&gt;The instance that was passed in.&lt;/returns&gt; public static IBindingWithSyntax&lt;TBinding&gt; WithPropertyValue&lt;TBinding, T&gt;(this IBindingWithSyntax&lt;TBinding&gt; instance, Expression&lt;Func&lt;TBinding, T&gt;&gt; propertyGetter, Func&lt;IContext, ITarget, T&gt; callback) { if (instance == null) { throw new ArgumentNullException("instance"); } if (propertyGetter == null) { throw new ArgumentNullException("propertyGetter"); } if (callback == null) { throw new ArgumentNullException("callback"); } PropertyInfo propertyInfo = getPropertyInfo(typeof(TBinding), propertyGetter); Func&lt;IContext, ITarget, object&gt; baseCallback = (context, target) =&gt; callback(context, target); return instance.WithPropertyValue(propertyInfo.Name, baseCallback); } private static PropertyInfo getPropertyInfo&lt;T&gt;(Type bindingType, Expression&lt;T&gt; expression) { if (expression.Body.NodeType != ExpressionType.MemberAccess) { throw new ArgumentException("The expression did access a property.", "propertyGetter"); } MemberExpression memberExpression = (MemberExpression)expression.Body; if (memberExpression.Member.MemberType != MemberTypes.Property) { throw new ArgumentException("The expression did not access a property.", "propertyGetter"); } PropertyInfo propertyInfo = (PropertyInfo)memberExpression.Member; if (!propertyInfo.DeclaringType.IsAssignableFrom(bindingType)) { throw new ArgumentException("The expression did not access a property in the specified type.", "propertyGetter"); } return propertyInfo; } /// &lt;summary&gt; /// Injects every property with the bound type of the property. /// &lt;/summary&gt; /// &lt;typeparam name="TBinding"&gt;The type of the object to set the property for.&lt;/typeparam&gt; /// &lt;param name="instance"&gt;Used to add additional information to a binding.&lt;/param&gt; /// &lt;returns&gt;The instance that was passed in.&lt;/returns&gt; public static IBindingWithSyntax&lt;TBinding&gt; SetAllProperties&lt;TBinding&gt;(this IBindingWithSyntax&lt;TBinding&gt; instance) { if (instance == null) { throw new ArgumentNullException("instance"); } IBindingWithSyntax&lt;TBinding&gt; result = instance; foreach (PropertyInfo property in typeof(TBinding).GetProperties()) { PropertyInfo local = property; result = result.WithPropertyValue(local.Name, context =&gt; context.Kernel.Get(local.PropertyType)); } return result; } } } </code></pre> <p>This allows me to configure a typed repository set like this:</p> <pre><code>Bind&lt;IMyRepository&gt;().To&lt;MyRepository&gt;(); Bind&lt;MyRespositorySet&gt;().ToSelf() .WithPropertyValue(set =&gt; set.MyRepository); </code></pre> <p>I also took some time to create a Module builder to save me from needing to create a separate Module class for each unit test I write. But that is a pretty big chunk of code, so I'll leave it out.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload