通过与泛型和覆盖反射调用的方法 [英] Invoking a method via reflection with generics and overrides
问题描述
我想调用在Unity容器RegisterType方法。 。RegisterType共有16重写(其中一些是参数有些类型)
我试图执行等价的:
Container.RegisterType< IMyDataProvider,MockData.MockProvider>(MockData,新ContainerControlledLifetimeManager())
使用实现getMethod()是一个完全失败,所以最后我做这个丑陋的东西:
<$ p $ 。p>
MethodInfo的registerTypeGeneric = Container.GetType()的getMethods(BindingFlags.Public | BindingFlags.Instance)。
其中(P => p.ToString()==Microsoft.Practices.Unity.IUnityContainer RegisterType [TFrom,TTO(System.String,Microsoft.Practices.Unity.LifetimeManager,Microsoft.Practices.Unity。 InjectionMember []))FirstOrDefault();
MethodInfo的registerTypeSpecific = registerTypeGeneric.MakeGenericMethod(新类型[] {typeof运算(IMyDataProvider),Assembly.LoadFrom(MockData.dll)的GetType(MockData.MockProvider)。});
registerTypeSpecific.Invoke(集装箱,新的对象[] {MockData,新ContainerControlledLifetimeManager()});
和本精美的作品,直到它抱怨,因为我没有InjectionMember参数调用(他们可选的,我没有任何放弃)。因此,根据文档,我必须使用Type.InvokeMember()调用具有可选参数的方法
所以我这样做:
粘合剂粘合=新BootstrapperBinder();
Container.GetType()InvokeMember(RegisterType,
BindingFlags.Instance |。BindingFlags.Public | BindingFlags.OptionalParamBinding | BindingFlags.InvokeMethod,
粘结剂,
集装箱,
新的对象[] {MockData,新ContainerControlledLifetimeManager()});
我BoostrapperBinder类做这样的:
公众覆盖MethodBase BindToMethod(的BindingFlags bindingAttr,MethodBase []的比赛,裁判的对象[] ARGS,ParameterModifier []修饰符,System.Globalization.CultureInfo文化,字符串[]名称,出对象的状态)
{
型mockProvider = Assembly.LoadFrom(MockData.dll)的GetType(MockData.MockProvider);
状态=新的对象();
MethodInfo的MI = Container.GetType()的getMethods(BindingFlags.Public | BindingFlags.Instance)。
其中(P => p.ToString()==Microsoft.Practices.Unity.IUnityContainer RegisterType [TFrom,TTO(System.String,Microsoft.Practices.Unity.LifetimeManager,Microsoft.Practices.Unity。 InjectionMember []))FirstOrDefault();
返回mi.MakeGenericMethod(新类型[] {typeof运算(ICarrierApprovalDataChangeAccessorEndPoint),mockProvider});
}
是的,它的丑陋,但我只是用它为这个OEN情况下,这样它的工作。
现在的问题是,它仍然在抱怨缺少第三个参数。我不能传递null或Missing.Value要么,或者croaks。我试过与无BindingFlags.OptionalParamBinding。我难倒。
(编辑把代码中的Container.RegisterType例子)
我最初的帖子中提到,我曾试图传递null作为第三个参数和应用嘶哑的声音。具体来说,它得到一个空引用异常,我应该已经了解了更加清晰。
解决的办法是通过新InjectionMember [0],而不是空,所以调用()应该是这个样子的:
registerTypeSpecific.Invoke(集装箱,新的对象[] {MockData新ContainerControlledLifetimeManager(),新InjectionMember [0]});
感谢杰森对他的帮助。他的样本送我失望,最终导致答案的路径。
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 trying to perform the equivalent of:
Container.RegisterType<IMyDataProvider, MockData.MockProvider>("MockData", new ContainerControlledLifetimeManager())
Using GetMethod() was a total failure, so I ended up doing this ugly thing:
MethodInfo registerTypeGeneric = Container.GetType().GetMethods(BindingFlags.Public | BindingFlags.Instance).
Where(p => p.ToString() == "Microsoft.Practices.Unity.IUnityContainer RegisterType[TFrom,TTo](System.String, Microsoft.Practices.Unity.LifetimeManager, Microsoft.Practices.Unity.InjectionMember[])").FirstOrDefault();
MethodInfo registerTypeSpecific = registerTypeGeneric.MakeGenericMethod( new Type[] { typeof(IMyDataProvider), Assembly.LoadFrom("MockData.dll").GetType("MockData.MockProvider") });
registerTypeSpecific.Invoke(Container, new object[] { "MockData", new ContainerControlledLifetimeManager() });
And this works beautifully, up until the Invoke which complains because I have no InjectionMember parameters (they're optional and I don't have any to give). So, according to the documentation, I have to use Type.InvokeMember() to call a method with optional parameters.
So I did this:
Binder binder = new BootstrapperBinder();
Container.GetType().InvokeMember("RegisterType",
BindingFlags.Instance | BindingFlags.Public | BindingFlags.OptionalParamBinding | BindingFlags.InvokeMethod,
binder,
Container,
new object[] { "MockData", new ContainerControlledLifetimeManager() });
My BoostrapperBinder class does this:
public override MethodBase BindToMethod(BindingFlags bindingAttr, MethodBase[] match, ref object[] args, ParameterModifier[] modifiers, System.Globalization.CultureInfo culture, string[] names, out object state)
{
Type mockProvider = Assembly.LoadFrom("MockData.dll").GetType("MockData.MockProvider");
state = new object();
MethodInfo mi = Container.GetType().GetMethods(BindingFlags.Public | BindingFlags.Instance).
Where(p => p.ToString() == "Microsoft.Practices.Unity.IUnityContainer RegisterType[TFrom,TTo](System.String, Microsoft.Practices.Unity.LifetimeManager, Microsoft.Practices.Unity.InjectionMember[])").FirstOrDefault();
return mi.MakeGenericMethod(new Type[] { typeof(ICarrierApprovalDataChangeAccessorEndPoint), mockProvider });
}
Yes, it's ugly, but I just use it for this oen case, so it does the job.
Now, the problem is, it's still complaining about the lack of a third parameter. I can't pass null or Missing.Value either, or it croaks. I've tried with and without BindingFlags.OptionalParamBinding. I'm stumped.
(Edited to put the Container.RegisterType example in code)
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.
这篇关于通过与泛型和覆盖反射调用的方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!