如何使用反射通过属性标记名称设置属性值?

Wil*_*ler 6 .net reflection attributes ldap active-directory

我希望编写一个可重用的库,用于使用LDAP查询AD.我正在使用ActiveDs COM对象和System.DirectoryServices.

受Bart de Smet LINQ到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
Run Code Online (Sandbox Code Playgroud)

这是我的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
Run Code Online (Sandbox Code Playgroud)

现在,我想从我放在User类属性之上的那些属性中受益.我知道如何获得这些属性,我知道如何获取我的属性.我不确定的是如何确保将正确的属性从SearchResult类设置为我的User类的正确值.

编辑随着时间的推移,我迫不及待地想要了解DirectorySource(Of T)的概念,因为它需要更多编码才能让我编写以使其正常工作.作为一种解决方法,我正在编写一个UserFactory类,它将通过我的ActiveDirectoryFacade调用.

编辑这个问题似乎与我希望完成的事情非常接近:
反思,属性和属性选择

编辑这看起来像我想要的:C#通过属性反射设置属性值
任何人有另一个想法或可以确认这是正确的?

我还要提一下,我陷入了.NET Framework 2.0和VBNET2005.否则,我会使用Bart de Smet的LINQ to AD库.

谢谢你的帮助.

And*_*zub 3

我不熟悉 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]);
            }
        }
    }
Run Code Online (Sandbox Code Playgroud)

如果您要填充的属性名称可以更改,您可以将属性映射存储在字典中。