J'optimise du code que nous utilisons pour interroger Active Directory. L'une des méthodes récupère tous les utilisateurs AD qui ont changé depuis une mise à jour particulière, déterminée par la propriété uSNCreated de l'entrée d'annuaire. Essentiellement, il est fait le C# équivalent de:Obtenir la méthode Invokable à partir de __ComObject
select * from PrincipalSearcher où uSNCreated> somevalue
Le code est (plus ou moins):
public IEnumerable<UserPrincipal> GetUpdatedUsers(string samAccountName, long lastUsnChanged)
{
using (var context = new PrincipalContext(ContextType.Domain))
using (var userSearcher = new PrincipalSearcher(new UserPrincipal(context)))
{
var items = userSearcher.FindAll().Cast<UserPrincipal>();
return items.Where(x => GetUsnChanged(x) > lastUsnChanged).ToArray();
}
}
private static long GetUsnChanged(Principal item)
{
var de = item.GetUnderlyingObject() as DirectoryEntry;
if (de == null)
return 0;
if (!de.Properties.Contains("uSNCreated"))
return 0;
var usn = de.Properties["uSNCreated"].Value;
var t = usn.GetType();
var highPart = (int)t.InvokeMember("HighPart", BindingFlags.GetProperty, null, usn, null);
var lowPart = (int)t.InvokeMember("LowPart", BindingFlags.GetProperty, null, usn, null);
return highPart * ((long)uint.MaxValue + 1) + lowPart;
}
Maintenant, ce code fonctionne, mais les appels répétés à InvokeMember() sont SLOW. Ce que je voudrais faire est d'obtenir une référence aux propriétés HighPart et LowPart afin que je puisse les appeler encore et encore sans avoir à les redécouvrir chaque fois que j'appellerai InvokeMember().
je bien que je pouvais faire quelque chose le long des lignes de
static PropertyInfo highProp = highProp
?? t.GetProperty("HighPart", BindingFlags.GetProperty);
highPart = (int)highProp.GetValue(usn);
Unfortnately t.GetProperty() retourne toujours null. En regardant les résultats retournés par GetProperties(), GetMethods() et GetMembers(), il ne semble pas y avoir un "HighPart" ou "LowPart" visible que je peux atteindre, même en utilisant BindingFlags.NonPublic - le __ComObject simplement ne semble pas les exposer (même si je peux appeler l'utilisation InvokeMember())
Existe-t-il un moyen de résoudre cela, ou est-il temps d'admettre la défaite?
Vous pouvez copier/coller la [déclaration d'interface] (https://referencesource.microsoft.com/#System.Web/Security/ADMembershipProvider.cs,96419c0a980e9d0e). Ou ajoutez une référence à c: \ windows \ system32 \ activeds.tlb. Convertissez la valeur de retour de la propriété Value en cette interface. Les chances que cela est réellement plus rapide ne sont pas si élevés, vous êtes sûrement juste de voir le coût du réseau aller-retour au contrôleur de domaine. –
Vous avez raison, cela ne semble pas faire quoi que ce soit pour la performance, mais cela rend le code plus lisible. Cela vaut un +1 dans mon livre - merci! – Pete