Directoryservices (d) '如果存在,则准备返回它 如果普林不是什么,那么 '如果对象是userprincipal,则获取该对象的用户详细主体。 如果TypeOf prin是UserPrincipal,那么 prin=UserDetailedPrinciple.FindBy

Directoryservices (d) '如果存在,则准备返回它 如果普林不是什么,那么 '如果对象是userprincipal,则获取该对象的用户详细主体。 如果TypeOf prin是UserPrincipal,那么 prin=UserDetailedPrinciple.FindBy,directoryservices,account-management,userprincipal,Directoryservices,Account Management,Userprincipal,(d) '如果存在,则准备返回它 如果普林不是什么,那么 '如果对象是userprincipal,则获取该对象的用户详细主体。 如果TypeOf prin是UserPrincipal,那么 prin=UserDetailedPrinciple.FindByIdentity(prin.Context,prin.Name) 如果prin的类型是GroupPrincipal prin=GroupPrincipal.FindByIdentity(prin.Context,prin.Name) 如果结束

(d) '如果存在,则准备返回它 如果普林不是什么,那么 '如果对象是userprincipal,则获取该对象的用户详细主体。 如果TypeOf prin是UserPrincipal,那么 prin=UserDetailedPrinciple.FindByIdentity(prin.Context,prin.Name) 如果prin的类型是GroupPrincipal prin=GroupPrincipal.FindByIdentity(prin.Context,prin.Name) 如果结束 "还校长, 加总(首席) 如果结束 下一个 “返回原则列表” 返回al.ToArray() 端函数 ''' ''获取八位字节字符串中包含的字节 ''' _ 公共函数extensiongetBytes(ByVal prin作为主体,ByVal属性作为字符串)作为Byte() “获取数据 Dim o As Object=ExtensionGetSingleValue(优先级,属性) '检查空值 如果o什么都不是 一无所获 如果结束 '获取字节数组 Dim byteArray()作为Byte=DirectCast(o,Byte()) '返回数据 回程 端函数 ''' ''获取包含在八位字节字符串类型属性中的图像 ''' _ 公共函数ExtensionGetImage(ByVal prin作为主体,ByVal属性作为字符串)作为图像 '获取属性的字节数 Dim bytearray()作为Byte=ExtentsionGetBytes(prin,属性) “如果没有返回,则什么也不返回 如果bytearray什么都不是 一无所获 如果结束 '将字节读入内存流 将ms变暗为新内存流(bytearray) '将内存流转换为位图并返回它 返回新位图(毫秒) 端函数 _ 公共函数ExtensionGetImages(ByVal prin作为主体,ByVal属性作为字符串)作为Image() '获取属性中的所有值 Dim VAL()作为对象=ExtensionGetAttribute对象(prin,属性) '用于保存要返回的图像的数组 Dim al作为新列表(图像)() 对于VAL中的每个o As对象 '获取字节 Dim bytearray()作为Byte=DirectCast(o,Byte()) '如果没有数据,则跳过输入 如果bytearray什么都不是 继续 如果结束 '将字节读入内存流 将ms变暗为新内存流(bytearray) '将内存流转换为位图并添加到数组中 al.添加(新位图(毫秒)) 下一个 '将图像列表作为数组返回。 返回al.ToArray() 端函数 #末端区域 #区域“设置帮助程序” 私有子扩展setde(ByVal de作为目录条目,ByVal属性作为字符串,ByVal值作为对象) '检查值,如果为null,则不添加(null仅表示清除) 如果值不是零,那么 de.Properties(属性).Add(值) 如果结束 端接头 _ 公共子扩展SetValue(ByVal prin作为主体,ByVal属性作为字符串,ByVal值作为对象) Dim uo As DirectoryEntry=prin.getUnderlineObject() uo.Properties(属性).Clear() ExtensionSetDE(uo、属性、值) 端接头 _ 公共子扩展SetStringValue(ByVal prin作为主体,ByVal属性作为字符串,ByVal值作为字符串) 如果String.IsNullOrEmpty(值),则 值=零 如果结束 ExtensionSetValue(优先级、属性、值) 端接头 _ 公共子扩展SetMultipleValueDirect(ByVal prin作为主体,ByVal属性作为字符串,ByVal values()作为对象) 'Normal ExtensionSet不支持保存数组类型值(八位字节字符串) '所以我们直接在底层对象上设置它 Dim uo As DirectoryEntry=prin.getUnderlineObject() uo.Properties(属性).Clear() 如果值不是零,那么 对于值中的每个v作为对象 ExtensionSetDE(uo、属性、v) 下一个 如果结束 端接头 _ 公共子扩展SetImage(ByVal prin作为主体,ByVal属性作为字符串,ByVal img作为映像) '将数据设置为属性 ExtensionSetValue(prin,属性,img.SaveImageToByteArray()) 端接头 _ 公共子扩展SetImages(ByVal prin作为主体,ByVal属性作为字符串,ByVal img()作为图像) '数组列表以临时保存值 Dim al作为新的ArrayList() '将每个图像转换为字节数组 对于img中的每个i As图像 al.Add(i.SaveImageToByteArray()) 下一个 '将图像数组设置为属性上的值 ExtensionSetMultipleValueDirect(prin,属性,al.ToArray()) 端接头 _ 公共函数SaveImageToByteArray(ByVal img作为图像)作为字节() “创建一个内存条” 将ms变暗为新内存流() '将图像写入流 保存(ms,Imaging.ImageFormat.Jpeg) '将数据保存到字节数组 Dim bytes()为Byte=ms.ToArray() 返回字节 端函数 _ 公共子扩展SetMultipleDistingUIshedNames(ByVal prin作为主体,ByVal属性作为字符串,ByVal dns()作为主体) '将用户原则转换为可分辨名称 Dim sc作为新的ArrayList() 对于dns中的每个u作为UserDetailedPrinciple sc.Add(u.DifferentiedName) 下一个 ExtensionSetMultipleValueDirect(prin,属性,sc.ToArray()) 端接头 ''' ''通过调整主照片的大小并保存原始照片(可能调整为300xvariable),帮助设置缩略图照片 ''到JPEG照片。 ''' ''要用作用户缩略图的图像 ''调用此sub后仍需要调用.Save() ''因为此子项不调用save()。 ''' _ 公共子集合用户照片(ByVal prin作为主体,ByVal imgO作为图像) '调整图像的缩略图大小
    ''' <summary>
    ''' Checks if an attribute is available on the underlying object.
    ''' </summary>
    <Extension()> _
    Public Function IsAttributeDefined(ByVal prin As Principal, ByVal attribute As String) As Boolean
        'since some attributes may not exist in all schemas check to see if it exists first
        Dim uo As DirectoryEntry = DirectCast(prin.GetUnderlyingObject(), DirectoryEntry)

        'check for property, if it's not found return an empty array
        Return uo.Properties.Contains(attribute)
    End Function

#Region "Get Helpers"
    ''' <summary>
    ''' This function is the foundation for retrieving data
    ''' </summary>
    <Extension()> _
    Public Function ExtensionGetAttributeObject(ByVal prin As Principal, ByVal attribute As String) As Object()
        'check if the attribute exists on this object
        If IsAttributeDefined(prin, attribute) Then
            'if property exists then return the data
            Dim dirObj As DirectoryEntry = prin.GetUnderlyingObject()
            Dim val As Object() = (From c As Object In dirObj.Properties(attribute) Select c).ToArray()

            Return val
        Else
            'return an empty array if the attribute is not defined
            Return New Object(-1) {}
        End If
    End Function

    ''' <summary>
    ''' This is the primary function for retrieving attributes that contain only one value
    ''' </summary>
    <Extension()> _
    Public Function ExtensionGetSingleValue(ByVal prin As Principal, ByVal attribute As String) As Object
        'get the object
        Dim attributeValues() As Object = ExtensionGetAttributeObject(prin, attribute)

        'if the item length = 1 then return the first value, else don't
        If attributeValues.Length = 1 Then
            Return attributeValues(0)
        Else
            Return Nothing
        End If
    End Function

    ''' <summary>
    ''' Returns the string value of an attribute
    ''' </summary>
    ''' <remarks>(null if no value found)</remarks>
    <Extension()> _
    Public Function ExtensionGetSingleString(ByVal prin As Principal, ByVal attribute As String) As String
        Dim o As Object = ExtensionGetSingleValue(prin, attribute)
        If o IsNot Nothing Then
            Return o.ToString()
        Else
            Return String.Empty
        End If
    End Function

    ''' <summary>
    ''' Returns all of the strings contained in a multi-value attribute
    ''' </summary>
    <Extension()> _
    Public Function ExtensionGetMultipleString(ByVal prin As Principal, ByVal attribute As String) As String()
        'get the object array for this attribute
        Dim attributeValues() As Object = ExtensionGetAttributeObject(prin, attribute)

        'create a string array of the same length as the object array
        Dim array As String() = New String(attributeValues.Length - 1) {}

        'and copy over all items, converting them to strings as we go
        For i As Integer = 0 To attributeValues.Length - 1
            array(i) = attributeValues(i).ToString()
        Next

        'return the string array
        Return array
    End Function

    ''' <summary>
    ''' Returns the date value of an attribute 
    ''' </summary>
    ''' <remarks>(null if no value found)</remarks>
    <Extension()> _
    Public Function ExtensionGetSingleDate(ByVal prin As Principal, ByVal attribute As String) As String
        Dim o As Object = ExtensionGetSingleValue(prin, attribute)
        If o IsNot Nothing Then
            Dim dt As DateTime = Convert.ToDateTime(o)
            Return dt
        Else
            Return Nothing
        End If
    End Function

    ''' <summary>
    ''' Returns the principle represented by a column containing a single distinguished name
    ''' </summary>
    <Extension()> _
    Public Function ExtensionGetSingleDistinguishedName(ByVal prin As Principal, ByVal attribute As String) As Principal
        'get the distinguished name of the object as a string
        Dim dn As String = ExtensionGetSingleString(prin, attribute)

        'check for null
        If String.IsNullOrEmpty(dn) Then
            Return Nothing
        End If

        'get the principal represented by the DN
        Dim prinF As Principal = Principal.FindByIdentity(prin.Context, dn)

        'if it exists then prepare to return it
        If prinF IsNot Nothing Then
            'if the object is a userprincipal then get the user detailed principal for it.
            If TypeOf prinF Is UserPrincipal Then
                prinF = UserDetailedPrinciple.FindByIdentity(prin.Context, prinF.Name)
            End If

            'return the principal
            Return prinF
        End If

        'if all else fails return nothing
        Return Nothing
    End Function

    <Extension()> _
    Public Function ExtensionGetMultipleDistinguishedNames(ByVal prinParent As Principal, ByVal attribute As String) As Principal()
        'get the distinguished name of the object as a string
        Dim dn() As String = ExtensionGetMultipleString(prinParent, attribute)

        'array to hold list of principles
        Dim al As New List(Of Principal)()

        For Each d As String In dn
            'get the principal represented by the DN
            Dim prin As Principal = Principal.FindByIdentity(prinParent.Context, d)

            'if it exists then prepare to return it
            If prin IsNot Nothing Then
                'if the object is a userprincipal then get the user detailed principal for it.
                If TypeOf prin Is UserPrincipal Then
                    prin = UserDetailedPrinciple.FindByIdentity(prin.Context, prin.Name)
                ElseIf TypeOf prin Is GroupPrincipal Then
                    prin = GroupPrincipal.FindByIdentity(prin.Context, prin.Name)
                End If

                'return the principal
                al.Add(prin)
            End If
        Next

        'return list of principles
        Return al.ToArray()
    End Function

    ''' <summary>
    ''' Gets the bytes contained in an Octet String
    ''' </summary>
    <Extension()> _
    Public Function ExtentsionGetBytes(ByVal prin As Principal, ByVal attribute As String) As Byte()
        'get the data
        Dim o As Object = ExtensionGetSingleValue(prin, attribute)
        'check for nulls
        If o Is Nothing Then
            Return Nothing
        End If

        'get the byte array
        Dim byteArray() As Byte = DirectCast(o, Byte())

        'return the data
        Return byteArray
    End Function

    ''' <summary>
    ''' Gets the image contained in an Octet String type attribute
    ''' </summary>
    <Extension()> _
    Public Function ExtensionGetImage(ByVal prin As Principal, ByVal attribute As String) As Image
        'get bytes for attribute
        Dim bytearray() As Byte = ExtentsionGetBytes(prin, attribute)

        'if none returned return nothing
        If bytearray Is Nothing Then
            Return Nothing
        End If

        'read the bytes into a memory stream
        Dim ms As New MemoryStream(bytearray)

        'convert the memory stream to a bitmap and return it
        Return New Bitmap(ms)
    End Function

    <Extension()> _
    Public Function ExtensionGetImages(ByVal prin As Principal, ByVal attribute As String) As Image()
        'get all values in attribute
        Dim vals() As Object = ExtensionGetAttributeObject(prin, attribute)

        'array to hold images to be returned
        Dim al As New List(Of Image)()

        For Each o As Object In vals
            'get bytes
            Dim bytearray() As Byte = DirectCast(o, Byte())

            'if no data skip entry
            If bytearray Is Nothing Then
                Continue For
            End If

            'read the bytes into a memory stream
            Dim ms As New MemoryStream(bytearray)

            'convert the memory stream to a bitmap and add to the array
            al.Add(New Bitmap(ms))
        Next
        'return the list of images as an array.
        Return al.ToArray()
    End Function
#End Region

#Region "Set Helpers"
    Private Sub ExtensionSetDE(ByVal de As DirectoryEntry, ByVal attribute As String, ByVal value As Object)
        'check value, if it's null then don't add (null means clear only)
        If value IsNot Nothing Then
            de.Properties(attribute).Add(value)
        End If
    End Sub

    <Extension()> _
    Public Sub ExtensionSetValue(ByVal prin As Principal, ByVal attribute As String, ByVal value As Object)
        Dim uo As DirectoryEntry = prin.GetUnderlyingObject()
        uo.Properties(attribute).Clear()
        ExtensionSetDE(uo, attribute, value)
    End Sub

    <Extension()> _
    Public Sub ExtensionSetStringValue(ByVal prin As Principal, ByVal attribute As String, ByVal value As String)
        If String.IsNullOrEmpty(value) Then
            value = Nothing
        End If

        ExtensionSetValue(prin, attribute, value)
    End Sub

    <Extension()> _
    Public Sub ExtensionSetMultipleValueDirect(ByVal prin As Principal, ByVal attribute As String, ByVal values() As Object)
        'Normal ExtensionSet does not support saving array type values (octet string)
        ' so we set it directly on the underlying object
        Dim uo As DirectoryEntry = prin.GetUnderlyingObject()
        uo.Properties(attribute).Clear()

        If values IsNot Nothing Then
            For Each v As Object In values
                ExtensionSetDE(uo, attribute, v)
            Next
        End If
    End Sub

    <Extension()> _
    Public Sub ExtensionSetImage(ByVal prin As Principal, ByVal attribute As String, ByVal img As Image)
        'set data to attribute
        ExtensionSetValue(prin, attribute, img.SaveImageToByteArray())
    End Sub

    <Extension()> _
    Public Sub ExtensionSetImages(ByVal prin As Principal, ByVal attribute As String, ByVal img() As Image)
        'array list to hold the values temporarily
        Dim al As New ArrayList()

        'convert each image into a byte array
        For Each i As Image In img
            al.Add(i.SaveImageToByteArray())
        Next

        'set image array as value on attribute
        ExtensionSetMultipleValueDirect(prin, attribute, al.ToArray())
    End Sub

    <Extension()> _
    Public Function SaveImageToByteArray(ByVal img As Image) As Byte()
        'create a memory strea
        Dim ms As New MemoryStream()
        'write the image to the stream
        img.Save(ms, Imaging.ImageFormat.Jpeg)

        'save data to a byte array
        Dim bytes() As Byte = ms.ToArray()

        Return bytes
    End Function

    <Extension()> _
    Public Sub ExtensionSetMultipleDistinguishedNames(ByVal prin As Principal, ByVal attribute As String, ByVal dns() As Principal)
        'convert user principles into distinguished names
        Dim sc As New ArrayList()
        For Each u As UserDetailedPrinciple In dns
            sc.Add(u.DistinguishedName)
        Next

        ExtensionSetMultipleValueDirect(prin, attribute, sc.ToArray())
    End Sub

    ''' <summary>
    ''' Helps set the Thumbnail photo by resizing main photo and also saving original (possibly resized to 300xvariable)
    ''' to JpegPhoto.
    ''' </summary>
    ''' <param name="imgO">The iamge to use as the users thumbnail photo</param>
    ''' <remarks>You still NEED to call .Save() after calling this sub
    ''' as this sub does not call save().
    ''' </remarks>
    <Extension()> _
    Public Sub SetUserPhoto(ByVal prin As Principal, ByVal imgO As Image)
        'resize the image for thumbnail
        Dim imgN As Bitmap = ResizeImage(imgO, 100)

        'check if we need to resize for medium sized image (300px high max
        Dim imgM As Bitmap
        If imgO.Height > 300 Then
            imgM = ResizeImage(imgO, 300)
        Else
            imgM = imgO
        End If

        'save small image to the users profile
        ExtensionSetImage(prin, "thumbnailPhoto", imgN)
        'save original to the jpegPhoto attribute
        ExtensionSetImages(prin, "jpegPhoto", New Image() {imgM})
    End Sub

    Private Function ResizeImage(ByVal imgO As Bitmap, ByVal Height As Integer) As Bitmap
        'if the image is smaller/equal to the requested height return original
        If imgO.Height <= Height Then
            Return imgO
        End If

        'images are fixedHeightxVariable, so we need to calculate the variable portion
        Dim width As Integer = (Convert.ToDecimal(imgO.Width) / Convert.ToDecimal(imgO.Height)) * Height

        'resize the image
        Dim imgN As New Bitmap(width, Height)
        Dim g As Graphics = Graphics.FromImage(imgN)
        g.SmoothingMode = Drawing2D.SmoothingMode.AntiAlias
        g.InterpolationMode = Drawing2D.InterpolationMode.HighQualityBicubic

        'draw in resized form
        g.DrawImage(imgO, 0, 0, width, Height)

        'return resized image
        Return imgN
    End Function

    <Extension()> _
    Public Function Rename(ByVal prin As Principal, ByVal NewName As String) As Principal
        'escape commas
        NewName = NewName.Replace(",", "\,")

        'get directory object for move
        Dim de As DirectoryEntry = prin.GetUnderlyingObject()

        'move
        de.Rename(String.Format("CN={0}", NewName))
        de.CommitChanges()

        'get the new object by name and return it
        Return New ADConnection(prin.Context).GetPrincipalByName(prin.Guid.ToString())
    End Function
#End Region
<DirectoryObjectClass("user")> _
<DirectoryRdnPrefix("CN")> _
Public Class UserDetailedPrinciple
    Inherits UserPrincipal

    <DirectoryProperty("initials")> _
    Public Property MiddleInitial() As String
        Get
            Return ExtensionGetSingleString("initials")
        End Get
        Set(ByVal value As String)
            ExtensionSetStringValue("initials", value)
        End Set
    End Property

    <DirectoryProperty("wWWHomePage")> _
    Public Property HomePage() As String
        Get
            Return ExtensionGetSingleString("wWWHomePage")
        End Get
        Set(ByVal value As String)
            ExtensionSetStringValue("wWWHomePage", value)
        End Set
    End Property

    <DirectoryProperty("url")> _
    Public Property URLs() As String()
        Get
            Return ExtensionGetMultipleString("url")
        End Get
        Set(ByVal value As String())
            ExtensionSetMultipleValueDirect("url", value)
        End Set
    End Property

    <DirectoryProperty("info")> _
    Public Property Notes() As String
        Get
            Return ExtensionGetSingleString("info")
        End Get
        Set(ByVal value As String)
            ExtensionSetStringValue("info", value)
        End Set
    End Property

    Public ReadOnly Property ObjectType() As String
        Get
            Dim types() As String = ExtensionGetMultipleString("objectClass")
            Return types.Last()
        End Get
    End Property

    <DirectoryProperty("thumbnailPhoto")> _
    Public Property ThumbnailPhoto() As Image
        Get
            Return ExtensionGetImage("thumbnailPhoto")
        End Get
        Set(ByVal value As Image)
            ExtensionSetImage("thumbnailPhoto", value)
        End Set
    End Property

    <DirectoryProperty("thumbnailLogo")> _
    Public Property ThumbnailLogo() As Image
        Get
            Return ExtensionGetImage("thumbnailLogo")
        End Get
        Set(ByVal value As Image)
            ExtensionSetImage("thumbnailLogo", value)
        End Set
    End Property

    <DirectoryProperty("jpegPhoto")> _
    Public Property JpegPhoto() As Image()
        Get
            Return ExtensionGetImages("jpegPhoto")
        End Get
        Set(ByVal value As Image())
            ExtensionSetImages("jpegPhoto", value)
        End Set
    End Property

    <DirectoryProperty("title")> _
    Public Property Title() As String
        Get
            Return ExtensionGetSingleString("title")
        End Get
        Set(ByVal value As String)
            ExtensionSetStringValue("title", value)
        End Set
    End Property

    <DirectoryProperty("department")> _
    Public Property Department() As String
        Get
            Return ExtensionGetSingleString("department")
        End Get
        Set(ByVal value As String)
            ExtensionSetStringValue("department", value)
        End Set
    End Property

    <DirectoryProperty("company")> _
    Public Property Company() As String
        Get
            Return ExtensionGetSingleString("company")
        End Get
        Set(ByVal value As String)
            ExtensionSetStringValue("company", value)
        End Set
    End Property

    <DirectoryProperty("manager")> _
    Public Property Manager() As UserDetailedPrinciple
        Get
            Dim mgr As UserDetailedPrinciple = ExtensionGetSingleDistinguishedName("manager")

            If mgr IsNot Nothing Then
                If Me.Guid <> mgr.Guid Then
                    Return mgr
                End If
            End If

            Return Nothing
        End Get
        Set(ByVal value As UserDetailedPrinciple)
            'check for nulls
            If value Is Nothing Then
                ExtensionSetStringValue("manager", Nothing)
            Else
                ExtensionSetStringValue("manager", value.DistinguishedName)
            End If
        End Set
    End Property

    <DirectoryProperty("assistant")> _
    Public Property Assistant() As UserDetailedPrinciple
        Get
            Dim assist As UserDetailedPrinciple = ExtensionGetSingleDistinguishedName("assistant")

            If assist IsNot Nothing Then
                Return assist
            End If

            Return Nothing
        End Get
        Set(ByVal value As UserDetailedPrinciple)
            'check for nulls
            If value Is Nothing Then
                ExtensionSetStringValue("assistant", Nothing)
            Else
                ExtensionSetStringValue("assistant", value.DistinguishedName)
            End If
        End Set
    End Property

    <DirectoryProperty("directReports")> _
    Public Property DirectReports() As Principal()
        Get
            Dim dReports As Principal() = ExtensionGetMultipleDistinguishedNames("directReports")
            Return dReports
        End Get
        Set(ByVal value As Principal())
            ExtensionSetMultipleDistinguishedNames("directReports", value)
        End Set
    End Property

    <DirectoryProperty("homePhone")> _
     Public Property HomePhone() As String
        Get
            Return ExtensionGetSingleString("homePhone")
        End Get
        Set(ByVal value As String)
            ExtensionSetStringValue("homePhone", value)
        End Set
    End Property

    <DirectoryProperty("pager")> _
     Public Property Pager() As String
        Get
            Return ExtensionGetSingleString("pager")
        End Get
        Set(ByVal value As String)
            ExtensionSetStringValue("pager", value)
        End Set
    End Property

    <DirectoryProperty("otherTelephone")> _
    Public Property OtherTelephone() As String()
        Get
            Return ExtensionGetMultipleString("otherTelephone")
        End Get
        Set(ByVal value As String())
            ExtensionSetMultipleValueDirect("otherTelephone", value)
        End Set
    End Property

    <DirectoryProperty("physicalDeliveryOfficeName")> _
    Public Property PhysicalLocation() As String
        Get
            Return ExtensionGetSingleString("physicalDeliveryOfficeName")
        End Get
        Set(ByVal value As String)
            ExtensionSetStringValue("physicalDeliveryOfficeName", value)
        End Set
    End Property

    <DirectoryProperty("l")> _
    Public Property AddressCity() As String
        Get
            Return ExtensionGetSingleString("l")
        End Get
        Set(ByVal value As String)
            ExtensionSetStringValue("l", value)
        End Set
    End Property

    <DirectoryProperty("postOfficeBox")> _
    Public Property AddressPOBox() As String
        Get
            Return ExtensionGetSingleString("postOfficeBox")
        End Get
        Set(ByVal value As String)
            ExtensionSetStringValue("postOfficeBox", value)
        End Set
    End Property

    <DirectoryProperty("st")> _
    Public Property AddressState() As String
        Get
            Return ExtensionGetSingleString("st")
        End Get
        Set(ByVal value As String)
            ExtensionSetStringValue("st", value)
        End Set
    End Property

    <DirectoryProperty("streetAddress")> _
    Public Property Address() As String
        Get
            Return ExtensionGetSingleString("streetAddress")
        End Get
        Set(ByVal value As String)
            ExtensionSetStringValue("streetAddress", value)
        End Set
    End Property

    <DirectoryProperty("postalCode")> _
    Public Property AddressZipCode() As String
        Get
            Return ExtensionGetSingleString("postalCode")
        End Get
        Set(ByVal value As String)
            ExtensionSetStringValue("postalCode", value)
        End Set
    End Property

    <DirectoryProperty("c")> _
     Public Property AddressCountry() As String
        Get
            Return ExtensionGetSingleString("c")
        End Get
        Set(ByVal value As String)
            ExtensionSetStringValue("c", value)
        End Set
    End Property

    <DirectoryProperty("whenCreated")> _
    Public ReadOnly Property Created() As Nullable(Of DateTime)
        Get
            Return ExtensionGetSingleDate("whenCreated")
        End Get
    End Property

    <DirectoryProperty("whenChanged")> _
    Public ReadOnly Property LastModified() As Nullable(Of DateTime)
        Get
            Return ExtensionGetSingleDate("whenChanged")
        End Get
    End Property

    Public Sub New()
        MyBase.New(ADConnection.CurrentADPrincipalContext)
    End Sub
    Public Sub New(ByVal context As PrincipalContext)
        MyBase.New(context)

    End Sub

    Public Overloads Shared Function FindByIdentity(ByVal context As PrincipalContext, ByVal identityValue As String) As UserDetailedPrinciple
        Return DirectCast(Principal.FindByIdentityWithType(context, GetType(UserDetailedPrinciple), identityValue), UserDetailedPrinciple)
    End Function

    Public Overloads Shared Function FindByIdentity(ByVal context As PrincipalContext, ByVal identityType As IdentityType, ByVal identityValue As String) As UserDetailedPrinciple
        Return DirectCast(Principal.FindByIdentityWithType(context, GetType(UserDetailedPrinciple), identityType, identityValue), UserDetailedPrinciple)
    End Function
End Class