2010-03-03 206 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