2010-03-03 49 views
5

Tôi muốn viết một thư viện có thể tái sử dụng để truy vấn AD với LDAP. Tôi đang sử dụng cả hai đối tượng ActiveDs COM và System.DirectoryServices.Cách đặt giá trị thuộc tính thông qua tên thẻ thuộc tính bằng cách sử dụng sự phản chiếu?

Lấy cảm hứng từ Bart de Smet LINQ to AD, tôi đã viết một lớp SchemaAttribute và một lớp DirectoryAttributeAttribute để sử dụng với lớp DirectorySource (Of T) (Có, đó là VBNET, nhưng bất kỳ mã C# nào sẽ trợ giúp khi tôi thành thạo) bằng cả hai ngôn ngữ).

Bây giờ, khi truy vấn đối với AD bằng cách sử dụng LDAP (System.DirectoryServices), bạn có thể chọn thuộc tính/thuộc tính bạn muốn được tải bởi lớp DirectorySearcher. Sau đó, tôi đã viết cho mình một phương thức lấy ParramArray của String làm tham số của nó, để tôi thêm các thuộc tính LDAP vào phương thức DirectorySearcher.PropertiesToLoad() trong một câu lệnh foreach(). Dưới đây là một đoạn mã để làm cho nó rõ ràng (Giả sử rằng ldapProps tham số sẽ luôn luôn chứa giá trị (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 

Dưới đây là một mảnh của lớp người dùng của tôi:

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 

Bây giờ, tôi muốn để mang lại lợi ích cho những thuộc tính mà tôi đặt lên trên thuộc tính Lớp người dùng của mình. Tôi biết làm thế nào để có được những thuộc tính này, và tôi biết làm thế nào để có được tài sản của tôi. Những gì tôi không chắc chắn là làm thế nào để đảm bảo rằng các tài sản phải sẽ được thiết lập giá trị đúng từ lớp SearchResult đến lớp người dùng của tôi.

EDIT Khi thời gian chơi với tôi, tôi không thể đợi làm quen với khái niệm DirectorySource (Of T), vì nó yêu cầu mã hóa nhiều hơn một chút để tôi viết. Để giải quyết vấn đề này, tôi đang viết một lớp UserFactory sẽ được gọi thông qua ActiveDirectoryFacade của tôi.

EDIT này SO câu hỏi có vẻ là rất gần với những gì tôi muốn thực hiện:
Reflection, Attributes and Property Selection

EDIT này trông giống như những gì tôi muốn: C# setting property values through reflection with attributes
Bất cứ ai có ý tưởng khác hoặc có thể xác nhận điều này đúng?

Tôi cũng phải đề cập rằng tôi bị kẹt trong .NET Framework 2.0 và VBNET2005. Nếu không, tôi đã sử dụng thư viện LINQ của Bart de Smet cho thư viện AD.

Cảm ơn bạn đã được trợ giúp.

Trả lời

2

Tôi không quen thuộc với DirectoryServices, nhưng nếu tôi nhận được câu hỏi của bạn đúng, bạn có thể sử dụng phản xạ để thiết lập các thuộc tính của đối tượng người dùng của bạn. Để thiết lập các thuộc tính chính xác, bạn nên khớp tên của các thuộc tính với dữ liệu được lưu trong các thuộc tính trên các thuộc tính của đối tượng 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]); 
      } 
     } 
    } 

Nếu tên của thuộc tính bạn sắp điền có thể thay đổi, bạn có thể lưu trữ ánh xạ thuộc tính trong từ điển.

+0

Thú vị! Tôi nghĩ về cách tiếp cận này, nhưng có thể tìm thấy một cách đơn giản để làm cho nó hoạt động. Tôi đoán rằng tôi có thể làm cho nó hoạt động với cách tiếp cận của bạn. Tôi sẽ thử nó và cho bạn biết liệu nó có hoạt động không. Cảm ơn! –

Các vấn đề liên quan