How to set property value through an attribute tag name using reflection?
I wish to write a reusable library for querying against AD with LDAP. I'm using both ActiveDs COM objects and System.DirectoryServices.
Greatly inspired by Bart de Smet LINQ to AD, I have written a SchemaAttribute and an DirectoryAttributeAttribute classes to use with a DirectorySource(Of T) class (Yes, it's VBNET, but any C# code will help as I'm fluent in both languages).
Now, when querying against AD using LDAP (System.DirectoryServices), you may choose what property/attribute you wish to get loaded by the DirectorySearcher class. Then, I've written myself a method that takes a ParramArray of String as its parameter, so that I add the LDAP properties to the DirectorySearcher.PropertiesToLoad() method within a foreach() statement. Here's a piece of code to make it clear (Assuming that ldapProps parameter will always contain value(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
Here's a piece of my User class:
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
Now, I would like to benefit of those attributes that I put on top of my User class properties. I know how to get these attributes, and I know how to get my properties. What I am unsure is how to make sure that the right property will be set the right value from the SearchResult class to my User class.
EDIT As time plays against me, I can't wait to get acquainted with the concept of DirectorySource(Of T), as it requires a bit more coding for me to write to get it working. As a workaround, I'm writing a UserFactory class which will be called through my ActiveDirectoryFacade.
EDIT This SO question seems to be very close to what I wish to accomplish:
Reflection, Attributes and开发者_如何学编程 Property SelectionEDIT This looks like what I want: C# setting property values through reflection with attributes
Anyone has another idea or can confirm this is right?I shall also mention that I'm stuck in .NET Framework 2.0 and VBNET2005. Otherwise, I would have used Bart de Smet's LINQ to AD library.
Thanks for any help.
I'm not familiar with DirectoryServices, but if I got your question right you could use reflections to set the properties of your User object. To set the correct properties you should match names of the properties with data saved in the attributes on the properties of the User's object.
[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]);
}
}
}
If names of the properties you are going to fill can change you can store mapping of properties in Dictionary.
精彩评论