通过泛型和覆盖反射调用方法

Pet*_*ete 6 c# generics reflection overriding

我正在尝试在Unity容器中调用RegisterType方法.RegisterType总共有16个覆盖(其中一些是参数,有些是类型).

我正在尝试执行相当于:

Container.RegisterType<IMyDataProvider, MockData.MockProvider>("MockData", new ContainerControlledLifetimeManager())
Run Code Online (Sandbox Code Playgroud)

使用GetMethod()完全失败,所以我最终做了这个丑陋的事情:

     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() });
Run Code Online (Sandbox Code Playgroud)

这个工作很漂亮,一直到Invoke因为我没有InjectionMember参数而抱怨(它们是可选的,我没有任何给予).因此,根据文档,我必须使用Type.InvokeMember()来调用带有可选参数的方法.

所以我这样做了:

     Binder binder = new BootstrapperBinder();
     Container.GetType().InvokeMember("RegisterType",
        BindingFlags.Instance | BindingFlags.Public | BindingFlags.OptionalParamBinding | BindingFlags.InvokeMethod,
        binder,
        Container,
        new object[] { "MockData", new ContainerControlledLifetimeManager() });
Run Code Online (Sandbox Code Playgroud)

我的BoostrapperBinder类执行此操作:

  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 });
  }
Run Code Online (Sandbox Code Playgroud)

是的,这很丑陋,但我只是用它来做这个案子,所以它完成了这项工作.

现在,问题是,它仍然抱怨缺少第三个参数.我也不能传递null或Missing.Value,或者它会呱呱叫.我尝试过使用和不使用BindingFlags.OptionalParamBinding.我很难过.

(编辑将Container.RegisterType示例放在代码中)

Pet*_*ete 1

我最初的帖子提到我曾尝试将 null 作为第三个参数传递,并且应用程序“嘎嘎作响”。具体来说,它遇到了空引用异常,我应该更清楚这一点。

解决方案是传递“new InjectionMember[0]”而不是 null,因此 Invoke() 应该如下所示:

registerTypeSpecific.Invoke(Container, new object[] { "MockData", new ContainerControlledLifetimeManager(), new InjectionMember[0] }); 
Run Code Online (Sandbox Code Playgroud)

感谢杰森的帮助。他的样本让我走上了最终找到答案的道路。