Estoy tratando de invocar el método RegisterType en el contenedor de Unity. RegisterType tiene un total de 16 reemplazos (algunos de esos son parámetros, algunos son tipos).Invocando un método a través de la reflexión con genéricos e invalida
Estoy tratando de realizar el equivalente de:
Container.RegisterType<IMyDataProvider, MockData.MockProvider>("MockData", new ContainerControlledLifetimeManager())
Usando GetMethod() fue un fracaso total, por lo que terminó haciendo esta cosa fea:
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() });
y esto funciona muy bien , hasta la invocación que se queja porque no tengo parámetros InjectionMember (son opcionales y no tengo ninguno para dar). Entonces, según la documentación, tengo que usar Type.InvokeMember() para llamar a un método con parámetros opcionales.
Así lo hice:
Binder binder = new BootstrapperBinder();
Container.GetType().InvokeMember("RegisterType",
BindingFlags.Instance | BindingFlags.Public | BindingFlags.OptionalParamBinding | BindingFlags.InvokeMethod,
binder,
Container,
new object[] { "MockData", new ContainerControlledLifetimeManager() });
Mi clase BoostrapperBinder hace esto:
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 });
}
Sí, es feo, pero yo sólo lo utilizan para este caso oen, por lo que hace el trabajo.
Ahora, el problema es que sigue quejándose de la falta de un tercer parámetro. No puedo pasar null o Missing.Value tampoco, o croa. Lo he intentado con y sin BindingFlags.OptionalParamBinding. Estoy perplejo.
(editado para poner el ejemplo Container.RegisterType en código)
El LINQ en GetMethods falla debido a más de un retorno (tiene 16 anulaciones, algunas tienen diferentes parámetros de tipo genérico), pero si utilizo la forma de obtener la información del método, la invocación aún falla con un nulo excepción de referencia en el método RegisterType(). Como el contenedor no es nulo, solo puedo suponer que el parámetro nulo es la causa. – Pete
Eso es fácil de arreglar. Agregue un '.Where (m => m.GetGenericArguments(). Count() == 2)' antes de la llamada a 'SingleOrDefault'. – jason
En cuanto al problema que experimenta con 'null', intente invocar el método a través de una invocación de método estático (es decir, elimine la reflexión). Simplemente llame a 'Container.RegisterType (" MockData ", nuevo ContainerControlledLifetimeManager(), null)' y vea si obtiene el mismo problema. Si lo haces, el problema NO es la invocación dinámica y, en cambio, es otra cosa (¿quizás la forma en que configuraste el contenedor?). –
jason