2010-03-03 102 views
5

我想写一个可重复使用的库,用LDAP查询AD。我正在使用ActiveD的COM对象和System.DirectoryServices。我写了一个SchemaAttribute和一个DirectoryAttributeAttribute类用于DirectorySource(Of T)类(是的,它是VBNET,但任何C#代码都会帮助,因为我流利以两种语言)。如何使用反射通过属性标记名称设置属性值?

现在,当使用LDAP(System.DirectoryServices)对AD进行查询时,您可以选择DirectorySearcher类所希望装入的属性/属性。然后,我为自己写了一个方法,该方法将ParramArray的String作为其参数,以便将LDAP属性添加到foreach()语句中的DirectorySearcher.PropertiesToLoad()方法。下面是一段代码,使其明确(假设ldapProps参数将始终包含值(s)):

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到AD库。

感谢您的任何帮助。

回答

2

我对DirectoryServices不熟悉,但是如果我有你的问题,你可以使用反射设置你的用户对象的属性。要设置正确的属性,您应该将属性的名称与保存在用户对象的属性中的属性中的数据匹配。

[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中存储属性的映射。

+0

有趣!我想到了这种方法,但可以找到一个简单的方法来实现它。我想我可以让它与你的方法一起工作。我会尝试一下,让你知道它是否有效。谢谢! – 2010-03-10 00:03:13