.NET Attribute Value Conversion
We now know that ADSI converts LDAP data to ADSI data types via schema mapping. Developers who are familiar with programming ADSI in an unmanaged language (Visual Basic 6, VBScript, C++, etc.) have also observed that ADSI data types are converted to normal COM variant types such as BSTR and VT_I4 when using the automation-compliant ADSI interfaces. The final piece in the puzzle is to understand how these data types are converted into the .NET data types we actually use.
Things are a little bit complicated here because SDS uses two different mechanisms to convert ADSI data types to .NET data types. The DirectoryEntry classes (DirectoryEntry, PropertyCollection, PropertyValueCollection) use one mechanism, and the DirectorySearcher classes (DirectorySearcher, SearchResult, ResultPropertyCollection, ResultPropertyValueCollection) use another. As Table 6.1 shows, the net result is the same in most cases, but there are differences as well. First, let's understand how things work and then we'll talk about the differences.
Data-Type Conversion with the DirectoryEntry Family
As we previously explained, DirectoryEntry is essentially a wrapper around the IADs ADSI interface. IADs is an automation-compliant COM interface, so it returns standard COM automation data types when properties are accessed. The normal .NET/COM interop system has built-in marshaling for the standard variant types. For example, BSTR converts back and forth to System.String, VT_I4 converts to System.Int32, and VT_BOOL converts to System.Boolean.
With the DirectoryEntry family of classes, SDS takes advantage of the platform's built-in support for the standard COM variant types and essentially does nothing. We access values in PropertyValueCollection as .NET data types, and in most cases, we can ignore their COM origins.
Data-Type Conversion with the DirectorySearcher Family
As we also know, DirectorySearcher is essentially a wrapper around the ADSI IDirectorySearch interface. Unlike with IADs, however, IDirectorySearch is not automation compliant. It is designed for use by lowerlevel languages like C++ and it requires programmers to access the ADSI data types directly. It does not return standard COM variant types. In order to provide .NET programmers with standard .NET data types, the SDS implementers had to write their own marshaling code to do the conversion.
Why the Big Deal?
This is important to understand because not all ADSI data types convert directly to COM automation types. Specifically, ADSTYPE_LARGE_INTEGER, ADSTYPE_NT_SECURITY_DESCRIPTOR, ADSTYPE_DN_WITH_BINARY, and ADSTYPE_DN_WITH_STRING do not convert to standard variant types, but instead convert to an IDispatch that can be cast to a special ADSI interface that is automation compliant.
However, these IDispatch types in .NET are converted to a special internal .NET data type called System.__ComObject, instead of to something we know what to do with, such as System.String or System.Int32. In order to convert these values to .NET data types, some additional COM interop is required.
With the DirectorySearcher family, the same problem does not exist, since SDS contains an explicit mapping system for IDirectorySearch as well as conversions for these types. For example, ADSTYPE_LARGE_INTEGER is converted to System.Int64.
The result is that for most LDAP data types, DirectoryEntry and DirectorySearcher will convert to the exact same data type, but not always. Specifically, for the four types we mentioned previously, the marshaling is different. This inconsistency is a constant source of confusion for developers who are not expecting it.
Let's look at some specific types.