Descompilación RuntimeType.InvokeMember
produce este fragmento:
if ((bindingFlags & BindingFlags.CreateInstance) != BindingFlags.Default)
{
if (((bindingFlags & BindingFlags.CreateInstance) != BindingFlags.Default) && ((bindingFlags & (BindingFlags.SetProperty | BindingFlags.GetProperty | BindingFlags.SetField | BindingFlags.GetField | BindingFlags.InvokeMethod)) != BindingFlags.Default))
{
throw new ArgumentException(Environment.GetResourceString("Arg_CreatInstAccess"), "bindingFlags");
}
return Activator.CreateInstance(this, bindingFlags, binder, providedArgs, culture);
}
En otras palabras, InvokeMember
con los BindingFlags
llama Activator.CreateInstance
. Pasa por varias capas de llamada más (verificando enlaces, verificando argumentos) antes de ponerse a trabajar. Activator.CreateInstance<T>
es mucho más sucinta:
public static T CreateInstance<T>()
{
bool bNeedSecurityCheck = true;
bool canBeCached = false;
RuntimeMethodHandle emptyHandle = RuntimeMethodHandle.EmptyHandle;
return (T) RuntimeTypeHandle.CreateInstance(typeof(T) as RuntimeType, true, true, ref canBeCached, ref emptyHandle, ref bNeedSecurityCheck);
}
editado Se podría esperar que ésta sea más rápido, pero un método llamado RuntimeType.CreateInstanceSlow
también llamadas RuntimeTypeHandle.CreateInstance
para hacer el trabajo; se usa como alternativa si no se puede encontrar una entrada de caché Activador para el constructor. Haría algunas pruebas de rendimiento si estás buscando la solución más rápida de las dos.
FWIW: 'Activator.CreateInstance()' es más correcto para su primer ejemplo, ya que no requerirá un lanzamiento del resultado a 'T'. –
@Steve Guidi: Gracias. Actualizaré la pregunta. –