我希望编写一个可重用的库,用于使用LDAP查询AD。我正在使用ActiveDs COM对象和System.DirectoryServices。
受到Bart de Smet LINQ to AD的启发,我编写了一个SchemaAttribute和一个DirectoryAttributeAttribute类,用于DirectorySource(Of T)类(是的,它是VBNET,但是任何C#代码都会有所帮助,因为我能够流利地使用它两种语言)。
现在,在使用LDAP(System.DirectoryServices)查询AD时,您可以选择DirectorySearcher类要加载的属性/属性。然后,我自己写了一个方法,它将ParramArray of String作为参数,这样我就可以在foreach()语句中将LDAP属性添加到DirectorySearcher.PropertiesToLoad()方法中。这是一段明确的代码(假设ldapProps参数将始终包含值):
Public Function GetUsers(ByVal ParamArray ldapProps() As String) As IList(Of IUser)
Dim users As IList(Of IUser) = New List(Of IUser)
Dim user As IUser
Dim de As DirectoryEntry = New DirectoryEntry(Environment.UserDomainName)
Dim ds As DirectorySearcher = New DirectorySearcher(de, "(objectClass=user)")
For Each p As String In ldapProps
ds.PropertiesToLoad(p)
Next
Try
Dim src As SearchResultCollection = ds.FindAll()
For Each sr As SearchResult In src
user = New User()
// This is where I'm stuck... Depending on the ldapProps required, I will fill only these in my User object.
Next
End Function
这是我的User类的一部分:
Friend NotInheritable Class User
Implements IUser
Private _accountName As String
Private _firstName As String
<DirectoryAttributeAttribute("SAMAccountName")> _
Public Property AccountName As String
Get
Return _accountName
End Get
Set (ByVal value As String)
If (String.Equals(_accountName, value)) Then Return
_accountName = value
End Set
End Property
<DirectoryAttributeAttribute("givenName")> _
Public Property FirstName As String
Get
Return _firstName
End Get
Set (ByVal value As String)
If (String.Equals(_firstName, value)) Then Return
_firstName = value
End Set
End Property
End Class
现在,我想从我放在User类属性之上的那些属性中受益。我知道如何获得这些属性,我知道如何获取我的属性。我不确定的是如何确保将正确的属性从SearchResult类设置为我的User类的正确值。
编辑随着时间的推移,我迫不及待想要了解DirectorySource(Of T)的概念,因为它需要更多编码才能让我编写以使其正常工作。作为一种解决方法,我正在编写一个UserFactory类,它将通过我的ActiveDirectoryFacade调用。
编辑这个问题似乎与我希望完成的事情非常接近:
Reflection, Attributes and Property Selection
编辑这看起来像我想要的:C# setting property values through reflection with attributes
任何人有另一个想法或者可以确认这是对的吗?
我还要提到我被困在.NET Framework 2.0和VBNET2005中。否则,我会使用Bart de Smet的LINQ to AD库。
感谢您的帮助。
答案 0 :(得分:2)
我不熟悉DirectoryServices,但如果我的问题正确,您可以使用反射来设置User对象的属性。要设置正确的属性,您应该将属性的名称与用户对象属性中属性中保存的数据相匹配。
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false, Inherited = false)]
public class DirectoryAttributeAttribute : Attribute
{
public DirectoryAttributeAttribute(string propertyName)
{
PropertyName = propertyName;
}
public string PropertyName
{
get; set;
}
}
public class User
{
[DirectoryAttributeAttribute("SAMAccountName")]
public string AccountName
{
get; set;
}
[DirectoryAttributeAttribute("givenName")]
public string FirstName
{
get; set;
}
}
// Finds property info by name.
public static PropertyInfo FindProperty(this Type type, string propertyName)
{
foreach (PropertyInfo propertyInfo in type.GetProperties())
{
object[] attributes = propertyInfo.GetCustomAttributes(typeof(DirectoryAttributeAttribute, false));
foreach (DirectoryAttributeAttribute attribute in attributes)
{
if (attribute.PropertyName == propertyName)
{
return propertyInfo;
}
}
}
return null;
}
SearchResult searchResult = ...;
if (searchResult != null)
{
User user = new User();
Type userType = typeof (User);
foreach (string propertyName in searchResult.Properties.PropertyNames)
{
// Find property using reflections.
PropertyInfo propertyInfo = userType.FindProperty(propertyName);
if (propertyInfo != null) // User object have property with DirectoryAttributeAttribute and matching name assigned.
{
// Set value using reflections.
propertyInfo.SetValue(user, searchResult.Properties[propertyName]);
}
}
}
如果您要填充的属性的名称可以更改,则可以在Dictionary中存储属性的映射。