如何转换PropertyValueCollection到一个列表c# ?(ResultPropertyCollectio

本文关键字:列表 一个 ResultPropertyCollectio 何转换 转换 PropertyValueCollection | 更新日期: 2023-09-27 18:14:23

我写了一个查询从活动目录读取一些东西,但结果是某种"ResultPropertyCollection",这是我不熟悉的东西。

如何将此结果转换为我更熟悉的列表(如泛型列表),以便我可以对结果进行处理?

DirectoryEntry de = new DirectoryEntry("LDAP://" + this.rootLDAP);
    DirectorySearcher ds = new DirectorySearcher(de, "(& (objectcategory=Group))");
    
    ds.PropertiesToLoad.Add("samaccountname");
    ds.PropertiesToLoad.Add("memberof");
    ds.PropertiesToLoad.Add("samaccounttype");
    ds.PropertiesToLoad.Add("grouptype");
    ds.PropertiesToLoad.Add("member");
    ds.PropertiesToLoad.Add("objectcategory");
     
     var r = ( from SearchResult sr in ds.FindAll() select sr ) .ToArray();

如何转换PropertyValueCollection到一个列表c# ?(ResultPropertyCollectio

如果您只想要一个SearchResult类型的列表,您可以使用:

var r = ds.FindAll();
        
List<SearchResult> results = new List<SearchResult>();
foreach (SearchResult sr in r)
{
   results.Add(sr);
}

但是由于您希望从搜索结果中获得实际值,因此需要做更多的工作。

基本上,该集合包含您为搜索定义的所有属性—至少只要它们包含值!

你需要做的是创建一个类来保存这些值。两个元素memberOfmember本身可以包含多个值(它们是"多值")。属性)-所以你需要一个字符串列表:

public class YourType
{
    public string SamAccountName { get; set; }
    public int SamAccountType { get; set; }
    public int GroupType { get; set; }
    public string ObjectCategory { get; set; }
    public List<string> MemberOf { get; set; }
    public List<string> Member { get; set; }
}

然后,一旦您有了搜索结果,您需要遍历结果并为每个搜索结果创建YourType的新实例,并将它们粘贴到List<YourType>中:

foreach(SearchResult sr in ds.FindAll())
{
    YourType newRecord = ConvertToYourType(sr);
}

,在该方法中,您需要检查.Properties集合中的每个值并提取它:

public YourType ConvertToYourType(SearchResult result)
{
    YourType returnValue = new YourType();
    returnValue.MemberOf = new List<string>();
    returnValue.Member = new List<string>();
    if(result.Properties["samAccountName"] != null && result.Properties["samAccountName"].Count > 0)
    {
       returnValue.SamAccountName = result.Properties["samAccountName"][0].ToString();
    }
    // ..... and so on for each of your values you need to extract
    return returnValue;
}

一开始我也很困惑,但这一切都是关于获得属性集合项的类型。一旦我发现属性项的类型是System.Collections.DictionaryEntry,并且值是由ResultPropertyValueCollection项组成的集合,就可以进行简单的迭代了。

最后的结果是:

        bool attemptResult = false;
        string ldap = "LDAP:<Your A.D. specific connection string>";
        DirectoryEntry entry = new DirectoryEntry(ldap, username, password, AuthenticationTypes.Secure);
        try
        {
            DirectorySearcher searcher = new DirectorySearcher(entry);
            searcher.Filter = "(&(objectClass=User)(sAMAccountName=" + username + "))";
            SearchResult one = searcher.FindOne();
            attemptResult = true;
            string properties = "";
            string userData = JsonConvert.SerializeObject(one.Properties);
            foreach (System.Collections.DictionaryEntry de in one.Properties) {
                properties += (properties.Length > 0 ? ",'n" : "");
                properties += "'"" + de.Key + "'": [";
                ResultPropertyValueCollection vc = ((ResultPropertyValueCollection)de.Value);
                foreach (var val in vc) {
                    properties += "{'"type'": '"" + val.GetType().Name + "'", '"value'"; '"" + val.ToString() + "'"}";
                }
                properties += "]";
            }
            properties = properties.Replace("}{", "},{");
            string displayName = one.Properties["displayname"][0].ToString();
            string givenName = one.Properties["givenname"][0].ToString();
            string lastname =  one.Properties["sn"][0].ToString();
        }
        catch (Exception e) {
            //log the error;
        }            
        return attemptResult;

注意使用JsonConvert.SerializeObject快速简便地转换为字符串。这是一步转换。

我还通过使用foreach迭代执行了到字符串的个性化转换。这更多的是一个自学练习,从中我得到一个命名属性的值后,我可以找出属性是否有零,一个或多个值,并采取相应的行动,甚至验证对象类型,如果它是必要的。

这是在字符串变量,属性和userData中获得的值(为了隐私,删除了一些项)。

/* Value of userData Obtained with Json serializator*/
{"givenname":["First Name"],"samaccountname":["User.Name"],"cn":["First Name Last Name"],"pwdlastset":[131641282827115142],"whencreated":["2017-10-12T22:16:43"],"badpwdcount":[0],"displayname":["First Name Last Name"],"lastlogon":[131648243091569908],"samaccounttype":[805306368],"countrycode":[0],"objectguid":["SOMETHINGBASE64LIKE=="],"usnchanged":[52144153],"manager":["CN=The Name Of A Person,OU=Department Name,OU=City,OU=GroupName ,DC=Domain,DC=com"],"whenchanged":["2018-03-02T23:21:54"],"name":["First Name Last Name"],"objectsid":["SOMETHINGBASE64LIKE=="],"lastlogoff":[0],"lockouttime":[0],"badpasswordtime":[131647632246625185],"instancetype":[4],"primarygroupid":[513],"objectcategory":["CN=Person,CN=Schema,CN=Configuration,DC=Domain,DC=com"],"logoncount":[1073],"useraccountcontrol":[512],"description":["Some text"],"dscorepropagationdata":["1601-01-01T00:00:00"],"distinguishedname":["CN=First Name Last Name,OU=Department Name,OU=City,OU=GroupName ,DC=Domain,DC=com"],"objectclass":["top","person","organizationalPerson","user"],"adspath":["LDAP://Server/CN=First Name Last Name,OU=Department Name,OU=City,OU=GroupName ,DC=Domain,DC=com"],"usncreated":[39705915],"lastlogontimestamp":[131643676396776065],"userprincipalname":["User.Name@Domain.com"],"employeeid":["99999"],"accountexpires":[9223372036854775807],"department":["DepartmentName"],"codepage":[0],"sn":["Last Name"]}
/* value of properties, the string I concatenated */
"givenname": [{"type": "String", "value"; "First Name"}],
"samaccountname": [{"type": "String", "value"; "User.Name"}],
"cn": [{"type": "String", "value"; "First Name Last name"}],
"pwdlastset": [{"type": "Int64", "value"; "131641282827115142"}],
"whencreated": [{"type": "DateTime", "value"; "12/10/2017 10:16:43 p. m."}],
"badpwdcount": [{"type": "Int32", "value"; "0"}],
"displayname": [{"type": "String", "value"; "First Name Last name"}],
"lastlogon": [{"type": "Int64", "value"; "131648243091569908"}],
"samaccounttype": [{"type": "Int32", "value"; "805306368"}],
"countrycode": [{"type": "Int32", "value"; "0"}],
"objectguid": [{"type": "Byte[]", "value"; "System.Byte[]"}],
"usnchanged": [{"type": "Int64", "value"; "52144153"}],
"manager": [{"type": "String", "value"; "CN=Some Person Name,OU=Department name,OU=City,OU=Group Name,DC=Domain,DC=com"}],
"whenchanged": [{"type": "DateTime", "value"; "2/3/2018 11:21:54 p. m."}],
"name": [{"type": "String", "value"; "First Name Last name"}],
"objectsid": [{"type": "Byte[]", "value"; "System.Byte[]"}],
"lastlogoff": [{"type": "Int64", "value"; "0"}],
"lockouttime": [{"type": "Int64", "value"; "0"}],
"badpasswordtime": [{"type": "Int64", "value"; "131647632246625185"}],
"instancetype": [{"type": "Int32", "value"; "4"}],
"primarygroupid": [{"type": "Int32", "value"; "513"}],
"objectcategory": [{"type": "String", "value"; "CN=Person,CN=Schema,CN=Configuration,DC=Domain,DC=com"}],
"logoncount": [{"type": "Int32", "value"; "1073"}],
"useraccountcontrol": [{"type": "Int32", "value"; "512"}],
"description": [{"type": "String", "value"; "13065, PROGRAMADOR SENIOR"}],
"dscorepropagationdata": [{"type": "DateTime", "value"; "1/1/1601 12:00:00 a. m."}],
"distinguishedname": [{"type": "String", "value"; "CN=First Name Last name,OU=Department name,OU=City,OU=Group Name,DC=Domain,DC=com"}],
"objectclass": [{"type": "String", "value"; "top"},{"type": "String", "value"; "person"},{"type": "String", "value"; "organizationalPerson"},{"type": "String", "value"; "user"}],
"adspath": [{"type": "String", "value"; "LDAP://SERVERNAME/CN=First Name Last name,OU=Department name,OU=City,OU=Group Name,DC=Domain,DC=com"}],
"usncreated": [{"type": "Int64", "value"; "39705915"}],
"lastlogontimestamp": [{"type": "Int64", "value"; "131643676396776065"}],
"userprincipalname": [{"type": "String", "value"; "User.Name@Domain.com"}],
"employeeid": [{"type": "String", "value"; "13065"}],
"accountexpires": [{"type": "Int64", "value"; "9223372036854775807"}],
"department": [{"type": "String", "value"; "IT"}],
"codepage": [{"type": "Int32", "value"; "0"}],
"sn": [{"type": "String", "value"; "Last name"}]

可以看到,有些属性有多个值。因此,要获得一个简单的通用属性列表,您需要决定如何处理多值属性。最有可能的是,您希望所有的值都是字符串,因此,可以简单地使用合适的分隔符将多个值连接起来。

这可能不是一个完整的解决方案或正确的答案。下面只是一个将SearchResultCollection转换为List的解决方案

SearchResultCollection rc = ds.FindAll();
List<SearchResult> resultList = rc.Cast<SearchResult>().ToList();
// Now loop through the list
foreach(SearchResult sr in resultList)
{
    //.. get properties here
}

我们不能用这样的东西吗?(因为我现在正在使用它)

ds.FindAll().Cast<SearchResult>().Select(result => new Address(result.GetDirectoryEntry())).ToList();
public class Address
{
    internal Address(DirectoryEntry entry)
    {
        //
        // You can get one or more of the following properties:
        //
        //
        // objectClass
        // cn
        // description
        // givenName
        // distinguishedName
        // instanceType
        // whenCreated
        // whenChanged
        // displayName
        // uSNCreated
        // memberOf
        // uSNChanged
        // homeMTA
        // proxyAddresses
        // homeMDB
        // mDBUseDefaults
        // mailNickname
        // protocolSettings
        // name
        // objectGUID
        // userAccountControl
        // badPwdCount
        // codePage
        // countryCode
        // badPasswordTime
        // lastLogon
        // pwdLastSet
        // primaryGroupID
        // objectSid
        // accountExpires
        // logonCount
        // sAMAccountName
        // sAMAccountType
        // showInAddressBook
        // legacyExchangeDN
        // userPrincipalName
        // lockoutTime
        // objectCategory
        // dSCorePropagationData
        // lastLogonTimestamp
        // textEncodedORAddress
        // mail
        // msExchPoliciesExcluded
        // msExchMailboxTemplateLink
        // msExchRecipientDisplayType
        // msExchUserCulture
        // msExchVersion
        // msExchRecipientTypeDetails
        // msExchHomeServerName
        // msExchALObjectVersion
        // msExchMailboxSecurityDescriptor
        // msExchUserAccountControl
        // msExchMailboxGuid
        // nTSecurityDescriptor
        // As an example we get only two properties
        this.DisplayName = (string)entry.Properties["displayName"].Value;
        this.Mail = (string)entry.Properties["mail"].Value;
        Manager = (string)entry.Properties["manager"].Value;
    }
    public string DisplayName
    {
        get;
        private set;
    }
    public string Manager
    {
        get;
        private set;
    }
    public string Mail
    {
        get;
        private set;
    }
}