通过与泛型和覆盖反射调用的方法 [英] Invoking a method via reflection with generics and overrides

查看:158
本文介绍了通过与泛型和覆盖反射调用的方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想调用在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.P​​ractices.Unity.IUnityContainer RegisterType [TFrom,TTO(System.String,Microsoft.P​​ractices.Unity.LifetimeManager,Microsoft.P​​ractices.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.P​​ractices.Unity.IUnityContainer RegisterType [TFrom,TTO(System.String,Microsoft.P​​ractices.Unity.LifetimeManager,Microsoft.P​​ractices.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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆