décompilation RuntimeType.InvokeMember
donne ce fragment:
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 d'autres termes, InvokeMember
avec ceux BindingFlags
appelle Activator.CreateInstance
. Il passe par plusieurs autres couches d'appel (vérifiant les liaisons, vérifiant les arguments) avant de se mettre au travail. Activator.CreateInstance<T>
est beaucoup plus succincte:
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);
}
ÉDITÉE Vous pourriez vous attendre que ce dernier soit plus rapide, mais une méthode appelée RuntimeType.CreateInstanceSlow
appelle également RuntimeTypeHandle.CreateInstance
à faire le travail; il est utilisé comme solution de repli si une entrée de cache Activator pour le constructeur est introuvable. Je ferais quelques tests de performance si vous cherchez la solution la plus rapide des deux.
FWIW: 'Activator.CreateInstance()' est plus correct pour votre premier exemple, car il ne nécessitera pas une distribution du résultat à 'T'. –
@Steve Guidi: Merci. Je vais mettre à jour la question. –