Decompiling RuntimeType.InvokeMember
cede questo frammento:
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);
}
In altre parole, InvokeMember
con quelli BindingFlags
chiama Activator.CreateInstance
. Passa attraverso molti altri livelli di chiamata (controllando i collegamenti, verificando gli argomenti) prima di mettersi al lavoro. Activator.CreateInstance<T>
è molto più succinta:
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);
}
a cura Ci si potrebbe aspettare a quest'ultimo di essere più veloce, ma un metodo chiamato RuntimeType.CreateInstanceSlow
chiamate anche RuntimeTypeHandle.CreateInstance
per fare il lavoro; è usato come fallback se non è possibile trovare una voce della cache di Activator per il costruttore. Farei dei test delle prestazioni se stai cercando la soluzione più veloce tra i due.
fonte
2009-08-18 17:54:48
FWIW: 'Activator.CreateInstance()' è più corretto per il tuo primo esempio, in quanto non richiede un cast del risultato a 'T'. –
@Steve Guidi: Grazie. Aggiornerò la domanda –