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

时间:2022-11-27 18:14:03

I wish to write a reusable library for querying against AD with LDAP. I'm using both ActiveDs COM objects and System.DirectoryServices.

我希望编写一个可重用库,用于使用LDAP查询AD。我使用了ActiveDs COM对象和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).

受到Bart de Smet LINQ到AD的启发,我编写了一个SchemaAttribute和DirectoryAttributeAttribute类,用于DirectorySource(T)类(是的,它是VBNET,但是任何c#代码都可以帮助我熟练地使用这两种语言)。

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)):

现在,当使用LDAP (System.DirectoryServices)查询AD时,您可以选择希望由DirectorySearcher类加载的属性/属性。然后,我为自己编写了一个方法,该方法以字符串的ParramArray作为参数,因此我将LDAP属性添加到foreach()语句中的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

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.

现在,我想从我在User类属性上添加的那些属性中获益。我知道如何获取这些属性,也知道如何获取属性。我不确定的是,如何确保将SearchResult类中的正确值设置为User类。

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.

随着时间的流逝,我迫不及待地想要了解DirectorySource(T)的概念,因为我需要多写一些代码才能让它工作。作为解决方案,我正在编写一个UserFactory类,它将通过我的ActiveDirectoryFacade被调用。

EDIT This SO question seems to be very close to what I wish to accomplish:
Reflection, Attributes and Property Selection

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

EDIT This looks like what I want: C# setting property values through reflection with attributes
Anyone has another idea or can confirm this is right?

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

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.

我还将提到,我被困在。net Framework 2.0和VBNET2005中。否则,我将使用Bart de Smet的LINQ到AD库。

Thanks for any help.

感谢任何帮助。

1 个解决方案

#1


2  

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.

我不熟悉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]);
            }
        }
    }

If names of the properties you are going to fill can change you can store mapping of properties in Dictionary.

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

#1


2  

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.

我不熟悉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]);
            }
        }
    }

If names of the properties you are going to fill can change you can store mapping of properties in Dictionary.

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