【发布时间】:2017-10-17 08:54:03
【问题描述】:
我正在优化我们用来查询 Active Directory 的一些代码。其中一种方法获取自特定更新以来已更改的所有 AD 用户,由目录条目的 uSNCreated 属性确定。本质上,它相当于 C#:
select * from PrincipalSearcher where uSNCreated > somevalue
代码是(或多或少):
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;
}
现在这段代码可以工作了,但是对 InvokeMember() 的重复调用很慢。我想做的是获取对 HighPart 和 LowPart 属性的引用,这样我就可以一遍又一遍地调用它们,而无需每次调用 InvokeMember() 时都需要“重新发现”它们。
我想我可以做一些类似的事情
static PropertyInfo highProp = highProp
?? t.GetProperty("HighPart", BindingFlags.GetProperty);
highPart = (int)highProp.GetValue(usn);
不幸的是 t.GetProperty() 总是返回 null。查看 GetProperties()、GetMethods() 和 GetMembers() 返回的结果,似乎没有可见的“HighPart”或“LowPart”,即使使用 BindingFlags.NonPublic - __ComObject 也是如此似乎没有暴露它们(即使我可以调用 using InvokeMember())
有没有办法解决这个问题,还是该认输了?
【问题讨论】:
-
您可以复制/粘贴interface declaration。或者添加对 c:\windows\system32\activeds.tlb 的引用。将 Value 属性的返回值强制转换为该接口。这实际上更快的可能性并不高,您肯定只是看到网络往返域控制器的成本。
-
你说得对,这似乎对性能没有任何影响,但它确实使代码更具可读性。这在我的书中值得 +1 - 谢谢!
标签: c# active-directory invoke comobject