I\'m trying to invoke the RegisterType method in the Unity container. RegisterType has a total of 16 overrides (some of those are parameters some are types).
I\'m tr
My initial post mentioned that I had tried passing null as a 3rd parameter and that the app "croaked." Specifically, it was getting a null reference exception and I should have been more clear about that.
The solution was to pass "new InjectionMember[0]" instead of null, so the Invoke() should have looked like this:
registerTypeSpecific.Invoke(Container, new object[] { "MockData", new ContainerControlledLifetimeManager(), new InjectionMember[0] });
Thanks to Jason for his help. His sample sent me down the path that eventually led to the answer.
I can't pass
null
orMissing.Value
either, or it croaks.
Croaks how? You should be able to pass null
for a params
parameter (when you invoke a method like M(params object[] objects)
via M()
it will be the case that objects
is null within the method.
Second, you can lookup the method more cleanly. I don't have a compiler at my fingertips, but try this:
var registerTypeMethodInfo =
typeof(IUnityContainer).GetMethods()
.Where(m => m.Name == "RegisterType")
.Where(m => m.GetParameters()
.Select(p => p.ParameterType)
.SequenceEqual(new[] {
typeof(string),
typeof(LifetimeManager),
typeof(InjectionMember[])
})
)
.Where(m => m.GetGenericArguments().Count() == 2)
.SingleOrDefault();
Assert.NotNull(registerTypeMethodInfo);
var methodInfo =
registerTypeMethodInfo.MakeGenericMethod(new[] {
typeof(IMyDataProvider),
typeof(MockData.MockProvider)
});
Then invoke the method like so, passing null
for the params InjectionMember[]
parameter:
methodInfo.Invoke(
Container,
new object[] {
"MockData",
new ContainerControlledLifetimeManager(),
null
}
);
Sorry if it doesn't compile. If it doesn't compile, this will get you very close to a correct solution.
Here is a self-contained example that works:
namespace ParamsTest {
interface Foo {
void M<T>(string s, int n, params object[] objects);
}
class Bar : Foo {
public void M<T>(string s, int n, params object[] objects) {
Console.WriteLine(s);
Console.WriteLine(n);
Console.WriteLine(objects == null);
Console.WriteLine(typeof(T).Name);
}
}
internal class Program {
internal static void Main(string[] args) {
var genericMethodInfo =
typeof(Foo).GetMethods()
.Where(m => m.Name == "M")
.Where(m => m.GetParameters()
.Select(p => p.ParameterType)
.SequenceEqual(new[] {
typeof(string),
typeof(int),
typeof(object[])
})
)
.Where(m => m.GetGenericArguments().Count() == 1)
.SingleOrDefault();
var methodInfo =
genericMethodInfo.MakeGenericMethod(
new[] { typeof(DateTime) }
);
var bar = new Bar();
methodInfo.Invoke(bar, new object[] { "Hello, world!", 17, null });
}
}
}
This prints:
Hello, world!
17
True
DateTime
on the console.
I've tried with and without BindingFlags.OptionalParamBinding. I'm stumped.
params
is not part of the signature of a method. It is a compiler trick to allow variable-length parameter lists. BindingFlags.OptionalParamBinding
is for binding optional parameters to their default values.