ConstructorArgument.Inject breaks where Kernel.Get works - c#

Given the following classes:
interface IFoo { }
class Foo : IFoo { }
class Bar
{
public Bar(IFoo foo) { }
}
And the binding:
Bind<Bar>().ToConstructor(ctx => new Bar(ctx.Inject<Foo>()));
Calling kernel.Get<Bar>() throws the following exception:
An unhandled exception of type 'Ninject.ActivationException' occurred in Ninject.dll
Additional information: Error activating IFoo
No matching bindings are available, and the type is not self-bindable.
Activation path:
2) Injection of dependency IFoo into parameter foo of constructor of type Bar
1) Request for Bar
However, if I change my bindings to:
Bind<Bar>().ToMethod(ctx => new Bar(ctx.Kernel.Get<Foo>()));
I can get an instance of Bar as expected.
Why am I getting that exception? I was under the impression the two bindings are almost identical, and in both cases an instance of IFoo is never activated.
(Not) working fiddle can be seen here: https://dotnetfiddle.net/qmPFhr

This is not supported by ninject. The type specified in ctx.Inject<> must match the type of the constructor parameter exactly. Ninject is never actually executing your new Bar(...), it only analyses the expression to determine which constructor to use and how to inject the values.
There's two ways to adapt your code to make it work:
change the constructor of Bar to receive a Foo intead of an IFoo.
change the ToConstructor binding of Bar to have ctx.Inject<>() match the constructor of Bar (ctx.Inject<IFoo>()) and create a binding for IFoo:
.
Bind<IFoo>().To<Foo>();
Bind<Bar>().ToConstructor(ctx => new Bar(ctx.Inject<IFoo>()));
As per your request for documentation
No it's not documented in any other document than the source/api, that ctx.Inject<> is not actually executed, ever. However, it is quite obvious from the parameter of the method being an Expression<Func<..>> and not a Func<..>. If it would be executed, a Func<..> would suffice. Expression's are there so you can analyze their contents.
Also, when looking at the source of BindingBuilder.cs, the Inject<T1> method actually only does one thing: throwing an exception:
public T1 Inject<T1>()
{
throw new InvalidOperationException("This method is for declaration that a parameter shall be injected only! Never call it directly.");
}
Also see: http://ivanitskyi.blogspot.com/2013/06/linq-func-vs-expression.html
If, however, you're referring to documentation regarding that the type T at Inject<T> must be an exact match: The answer is no, again. I couldn't find any documentation about it. However, as it's open source, we can again resort to having a look at the implementation. Again, it's found in BindingBuilder.cs, which contains:
protected IBindingWhenInNamedWithOrOnSyntax<TImplementation> InternalToConstructor<TImplementation>(
Expression<Func<IConstructorArgumentSyntax, TImplementation>> newExpression)
{
var ctorExpression = newExpression.Body as NewExpression;
if (ctorExpression == null)
{
throw new ArgumentException("The expression must be a constructor call.", "newExpression");
}
this.BindingConfiguration.ProviderCallback = StandardProvider.GetCreationCallback(ctorExpression.Type, ctorExpression.Constructor);
this.BindingConfiguration.Target = BindingTarget.Type;
this.AddConstructorArguments(ctorExpression, newExpression.Parameters[0]);
return new BindingConfigurationBuilder<TImplementation>(this.BindingConfiguration, this.ServiceNames, this.Kernel);
}
And you can go from there an have a look at AddConstructorArguments and how that stuff works, and eventually you'll find out why it behaves as it does ;-)
(I'm not going to to that for you)

Related

Activator.CreateInstance works in one method but throws AmbiguousMatchException in another

I have two generic methods in the same class, and each uses exactly the same code to create instances. One works, the other throws an AmbiguousMatchException. Here is the code:
private static Dictionary<Type, AccessBase> _dictionary;
public static T Access<T>(Type type) where T : AccessBase
{
T instantiated;
if (_dictionary.ContainsKey(type))
{
instantiated = _dictionary[type] as T;
}
else
{
instantiated = (T)Activator.CreateInstance(type, _manager); //<- Works!
_dictionary.Add(type, instantiated);
}
return instantiated;
}
public static void RegisterAccess<T>(Type type) where T : AccessBase
{
if (type == null)
{
throw new ArgumentNullException(nameof(type));
}
if (_dictionary.ContainsKey(type))
{
return;
}
var instantiated = (T)Activator.CreateInstance(type, _manager); //<- Fails!
if (instantiated == null)
{
throw new ArgumentException($"{nameof(type)} cannot be registered");
}
_dictionary.Add(type, instantiated);
}
I would welcome any suggestions as to why and what to do about it... I have been tearing what is left of my hair out over this one!
Thanks to all of you for your input. I finally found the problem, which as it turns out is quite simple actually. At the point of failure the value of the _manager field is null... As soon as it is no longer null, it works.
To trap this I tried calling the first method at the same time as the second, and both failed. Tracking it through, I determined that the cause was the null value, since if you do it later in the process it works fine.
The original purpose of the code was to pre-register the access classes so that when they are needed they are ready to go and avoid the constant 'new' calls to generate these classes as they are needed. Given that it is now clear that this cannot happen at that point, the question is whether this is required at all. If we do it at a later point, there is not much reason to do it as it will get repeated every time a database is opened with each one not being added as it already exists.
I think we will end up abandoning the process that uses the second method, the pre-registration, in favour of the first method which is already used anyway and which automatically adds the instantiated classes only when they are needed and which already works fine at the later point.

In TPL Dataflow, is it possible to change DataflowBlockOptions after block is created but before it is used?

... and have it take effect?
I'd like to defer setting the ExecutionDataflowBlockOptions.SingleProducerConstrained property until I'm ready to link the network together. (Because, I want to separate creating the blocks, with their semantics, from linking the network together, with its semantics.)
But as far as I can tell you can only set the ExecutionDataflowBlockOptions when the block is created (e.g., for TransformBlock, TransformManyBlock, etc, you pass it in to the constructor and it is not visible otherwise).
However ... it hasn't escaped my notice that the properties have public setters. So ... can I create the block with a placeholder instance of ExecutionDataflowBlockOptions and hold on to it so that I can later set SingleProducerConstrained=true if I desire, when linking the blocks together (and that it will take effect)?
(BTW, is there any way to tell if SingleProducerConstrained is having any effect other than measuring throughput?)
Update: #i3amon correctly pointed out in his answer this can't be done because dataflow blocks clone the DataflowBlockOptions you pass in and use that. But I did it anyway, using internal data structures I can access via reflection and dynamic. I put that in an answer below.
It isn't possible. Modifying the options after the fact won't work. The options are cloned inside the block's constructor. Changing the options later will have no effect.
You can see examples of that here and here and it's simple to verify:
var options = new ExecutionDataflowBlockOptions
{
NameFormat = "bar",
};
var block = new ActionBlock<int>(_ => { }, options);
options.NameFormat = "hamster";
Console.WriteLine(block.ToString());
Output:
bar
Let me answer my own question. Using information from DotNetInside's decompile of the Dataflow assembly, for example, TransformBlock here (thanks #i3amon again for the link to dotnetinside.com), and the very nice ExposedObject package at codeplex here (which I learned about at this blog post, I did the following:
The TPL Dataflow blocks all implement debugger visualizers via the DebuggerTypeProxy attribute, which, applied to a type, names another type to use in the Visual Studio debugger whenever the original type is to be displayed (e.g., watch window).
Each of these DebuggerTypeProxy-named classes are inner classes of the dataflow block the attribute is attached to, usually named DebugView. That class is always private and sealed. It exposes lots of cool stuff about the dataflow block, including its genuine (not a copy) DataflowBlockOptions and also - if the block is a source block - an ITargetBlock[], which can be used to trace the dataflow network from its start block after construction.
Once you get an instance of the DebugView you can use dynamic via ExposedObject to get any of the properties exposed by the class - ExposedObject lets you take an object and use ordinary method and property syntax to access its methods and properties.
Thus you can get the DataflowBlockOptions out of the dataflow block and change its NameFormat, and if it is an ExecutionDataflowBlockOptions (and you haven't yet hooked up the block to other blocks) you can change its SingleProducerConstrained value.
However you can't use dynamic to find or construct the instance of the inner DebugView class. You need reflection for that. You start by getting the DebuggerTypeProxy attribute off your
dataflow block's type, fetch the name of the debugging class, assume it is an inner class of
the dataflow block's type and search for it, convert it to a closed generic type, and finally
construct an instance.
Be fully aware that you're using undocumented code from the dataflow internals. Use your own
judgement about whether this is a good idea. In my opinion, the developers of TPL Dataflow did a lot of work to support viewing these blocks in the debugger, and they'll probably keep it up. Details may change, but, if you're doing proper error checking on your reflection and dynamic use of these types, you will be able to discover when your code stops working with a new version of TPL Dataflow.
The following code fragments probably don't compile together - they're simply cut&pasted out of my working code, from different classes, but they certainly give you the idea. I made it work fine. (Also, for brevity, I elided all error checking.) (Also, I developed/tested this code with version 4.5.20.0 only of TPL dataflow, so you may have to adapt it for past - or future! - versions.)
// Set (change) the NameFormat of a dataflow block after construction
public void SetNameFormat(IDataflowBlock block, string nameFormat)
{
try
{
dynamic debugView = block.GetInternalData(Logger);
if (null != debugView)
{
var blockOptions = debugView.DataflowBlockOptions as DataflowBlockOptions;
blockOptions.NameFormat = nameFormat;
}
}
catch (Exception ex)
{
...
}
}
// Get access to the internal data of a dataflow block via its DebugTypeProxy class
public static dynamic GetInternalData(this IDataflowBlock block)
{
Type blockType = block.GetType();
try
{
// Get the DebuggerTypeProxy attribute, which names the debug class type.
DebuggerTypeProxyAttribute debuggerTypeProxyAttr =
blockType.GetCustomAttributes(true).OfType<DebuggerTypeProxyAttribute>().Single();
// Get the name of the debug class type
string debuggerTypeProxyNestedClassName =
GetNestedTypeNameFromTypeProxyName(debuggerTypeProxyAttr.ProxyTypeName);
// Get the actual Type of the nested class type (it will be open generic)
Type openDebuggerTypeProxyNestedClass = blockType.GetNestedType(
debuggerTypeProxyNestedClassName,
System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic);
// Close it with the actual type arguments from the outer (dataflow block) Type.
Type debuggerTypeProxyNestedClass =
openDebuggerTypeProxyNestedClass.CloseNestedTypeOfClosedGeneric(blockType);
// Now create an instance of the debug class directed at the given dataflow block.
dynamic debugView = ExposedObject.New(debuggerTypeProxyNestedClass, block);
return debugView;
}
catch (Exception ex)
{
...
return null;
}
}
// Given a (Type of a) (open) inner class of a generic class, return the (Type
// of the) closed inner class.
public static Type CloseNestedTypeOfClosedGeneric(
this Type openNestedType,
Type closedOuterGenericType)
{
Type[] outerGenericTypeArguments = closedOuterGenericType.GetGenericArguments();
Type closedNestedType = openNestedType.MakeGenericType(outerGenericTypeArguments);
return closedNestedType;
}
// A cheesy helper to pull a type name for a nested type out of a full assembly name.
private static string GetNestedTypeNameFromTypeProxyName(string value)
{
// Expecting it to have the following form: full assembly name, e.g.,
// "System.Threading...FooBlock`1+NESTEDNAMEHERE, System..."
Match m = Regex.Match(value, #"^.*`\d+[+]([_\w-[0-9]][_\w]+),.*$", RegexOptions.IgnoreCase);
if (!m.Success)
return null;
else
return m.Groups[1].Value;
}
// Added to IgorO.ExposedObjectProject.ExposedObject class to let me construct an
// object using a constructor with an argument.
public ExposedObject {
...
public static dynamic New(Type type, object arg)
{
return new ExposedObject(Create(type, arg));
}
private static object Create(Type type, object arg)
{
// Create instance using Activator
object res = Activator.CreateInstance(type, arg);
return res;
// ... or, alternatively, this works using reflection, your choice:
Type argType = arg.GetType();
ConstructorInfo constructorInfo = GetConstructorInfo(type, argType);
return constructorInfo.Invoke(new object[] { arg });
}
...
}

Ninject get target type from IBinding

I have an Interface that is implemented by several types. But before I do a kernel.GetAll<IAmServiceable>() I want to be able to ponder the target types of the injection.
I know the function kernel.GetBindings(typeof(IAmServiceable)) exists but this returns a list of IBinding's.
Does anyone know how I can get the target type from the IBinding?
I want to know the type that is bound to IAmServiceable before it gets instantiated.
I know it's probably a bit late now for your problem, but since i ran into this today, i thought others might too.
That's the code i finally came up with - i don't think its perfect (far from it), especially regarding performance, but it works for my case, and since i do not intend to call this method very often, it seems ok to me.
public Type GetBoundToType(IKernel kernel, Type boundType)
{
var binding = kernel.GetBindings(boundType).FirstOrDefault();
if (binding != null)
{
if (binding.Target != BindingTarget.Type && binding.Target != BindingTarget.Self)
{
// TODO: maybe the code below could work for other BindingTarget values, too, feelfree to try
throw new InvalidOperationException(string.Format("Cannot find the type to which {0} is bound to, because it is bound using a method, provider or constant ", boundType));
}
var req = kernel.CreateRequest(boundType, metadata => true, new IParameter[0], true, false);
var cache = kernel.Components.Get<ICache>();
var planner = kernel.Components.Get<IPlanner>();
var pipeline = kernel.Components.Get<IPipeline>();
var provider = binding.GetProvider(new Context(kernel, req, binding, cache, planner, pipeline));
return provider.Type;
}
if (boundType.IsClass && !boundType.IsAbstract)
{
return boundType;
}
throw new InvalidOperationException(string.Format("Cannot find the type to which {0} is bound to", boundType));
}
This is not possible. E.g what is the type In this case?
Bind<IX>().ToMethod(c => RandomBool() ? new Foo() : new Bar());
If you are working within a NinjectModule (or have access to an IKernel some other way) A nice simple approach would be:
var concreteType = Kernel.Get<InterfaceType>().GetType();
Obviously, the downside is you create an instance of the concrete type. It is nevertheless nice and simple and I think pretty robust. Obviously, if the interface derives from IDisposable you would use a using statement:
using(var obj = Kernel.Get<InterfaceType>())
{
var concreteType = obj.GetType();
.
.
.
}

Reflection.Assembly.CreateInstance(string)

In .NET 4.0, if I have the following code:
....
T instantiatedClass;
try
{
instantiatedClass = (T)assembly.CreateInstance(classFullName);
}
catch (Exception ex)
{
errMsg = string.Format("Error creating an instance of type \"{0}\".", classes.First().FullName);
throw new ApplicationException(errMsg, ex);
}
Assuming that classFullName is a correct type in the assembly, and that the type "T" implements a public interface, is there any circumstance where 1) No exception would be thrown, and 2) instantiatedClass would be null?
Thanks for any help.
Based on your assumptions and if your type T is always an interface then a direct cast to T will throw an exception if the interface in question is not implemented by the created instance or if the type does not have a default constructor that can be called.
A better approach that avoids throwing an exception would be...
T interfaceVar = assembly.CreateInstance(classFullName) as T;
if (interfaceVar == null)
{
// oops, does not implement interface T
}
else
{
// yippee, it does implement interface T
}
You could use reflection on the target assembly to check if the required type exists, if it has a default constructor and if it implements the interface you are interested in. In that case you would avoid creating an instance at all, if all you want to know is if it has the specified interface.
If there is no default constructor or the assumption that classFullName is valid in the assembly is incorrect or anything prevents the CreateInstance call from calling a constructor an exception is thrown.
So the only way that this could fail for you is if the called constructor returns a null value. But this can't happen since if no exception is raised during construction, then the constructor call will return a reference to the new object, and if an exception is raised you catch it.

How to decide at runtime which type to pass as a generic parameter?

I have several message queues that have specific messages on them.
I've created classes for these messages using xsd.exe.
I can receive a message syncronously and deseriazlise it with this method:
public oneOfMyTypes DeserializeMessage(XDocument message)
{
var serializer = new XmlSerializer(typeof(oneOfMyTypes));
var entity = (oneOfMyTypes)serializer.Deserialize(message.CreateReader());
return entity;
}
I then persist the entity via Fluent NHibernate.
So I've got about five message queues that all have their own type of message.
I would like to keep this little processor app maintainable, so that adding more message queues and message types doesn't become a pain.
So I have a list of queue names in my app.config that I use to create the message queues on start up and then I want to wire up a single method to the .ReceiveCompleted event of all queues:
void queue_ReceiveCompleted(object sender, ReceiveCompletedEventArgs e)
{
var queue = (MessageQueue)sender;
var message = queue.EndReceive(e.AsyncResult);
var body = message.Body.ToString();
var xml = XDocument.Parse(body);
var queueName = queue.QueueName;
Type entityType = GetTypeFromQueueName(queueName);
entityType entity = DeserializeMessage<entityType>(xml);
var repository = new LogRepository();
repository.AddEntity<entityType>(entity);
}
private T DeserializeMessage<T>(XDocument message)
{
var serializer = new XmlSerializer(typeof(T));
var entity = (T)serializer.Deserialize(message.CreateReader());
return entity;
}
public Type GetTypeFromQueueName(string queueName)
{
switch (queueName)
{
case "some-message-queue-name":
return typeof (oneOfMyTypes);
}
}
But when I try to pass entityType to the generic methods I get "Type or namespace name expected".
I'm probably doing something really silly, but I can't figure out how this should work.
I've tried using the dynamic keyword and also .MakeGenericType but no luck.
I've also looked at:
Dynamic Generic declaration of type T
Function returning a generic type whose value is known only at runtime
Determining a Generic Type at Runtime in Non-Generic Class
How to pass variable of type "Type" to generic parameter
But I'm still not getting it ... help?
Unfortunately, generics are not meant to function dynamically like this. Generic parameters must be defined at design time. It's been a while since I've used NHibernate, but isn't there a way to insert entities with a syntax like:
repository.AddEntity(entity, typeof(myEntityType));
EDIT:
or
Session.SaveOrUpdate(object);
This link should help you
http://todotnet.com/post/2006/11/13/Instantiating-Generic-Types-at-runtime.aspx
You should be able to go from the link i posted to call the methode through reflection.
See the following link:
http://www.victorchen.info/call-static-method-with-a-string-name/
So basically when you've created your generic Type, you then grab the MethodInfo of your static method and then call the Invoke method on the MethodInfo object.
(i haven't actually tried this but in theory i believe it should work)

Categories

Resources