title: Mapping LDAP Data to .NET Classes (LINQ)
body: <p>I've been using several different tuts in order to build a LINQ-to-LDAP model.  I've just about got it complete, but I'm running into some issues trying to bind the data returned to a class.</p>
  
  <p>I do the reverse part by assigning custom attributes to the properties of the class that are the actual names of the database fields.  </p>
  
  <p>Here is an example of the class, as well as the custom attribute (the <code>DirectorySchemaAttribute</code> and <code>DirectoryRootAttribute</code> implementations are not included...  those pieces are working correctly):</p>
  
  <pre><code>[DirectorySchema("C4User"), DirectoryRoot("o=c4, ou=users")]
  class User
  {
      [DirectoryAttribute("cn")]
      public string Username { get; set; }
  
      [DirectoryAttribute("userpassword")]
      public string Password { get; set; }
  
      [DirectoryAttribute("C4-Parent")]
      public string Parent { get; set; }
  }
  
  
  /// &lt;summary&gt;
  /// Specifies the underlying attribute to query for in the directory.
  /// &lt;/summary&gt;
  [AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
  public class DirectoryAttributeAttribute : Attribute
  {
      private string attribute;
      private DirectoryAttributeType type;
  
      /// &lt;summary&gt;
      /// Creates a new attribute binding attribute for a entity class field or property.
      /// &lt;/summary&gt;
      /// &lt;param name="attribute"&gt;Name of the attribute to query for.&lt;/param&gt;
      public DirectoryAttributeAttribute(string attribute)
      {
          this.attribute = attribute;
          this.type = DirectoryAttributeType.Ldap;
      }
  
      /// &lt;summary&gt;
      /// Creates a new attribute binding attribute for a entity class field or property.
      /// &lt;/summary&gt;
      /// &lt;param name="attribute"&gt;Name of the attribute to query for.&lt;/param&gt;
      /// &lt;param name="type"&gt;Type of the underlying query source to get the attribute from.&lt;/param&gt;
      public DirectoryAttributeAttribute(string attribute, DirectoryAttributeType type)
      {
          this.attribute = attribute;
          this.type = type;
      }
  
      /// &lt;summary&gt;
      /// Name of the attribute to query for.
      /// &lt;/summary&gt;
      public string Attribute
      {
          get { return attribute; }
          set { attribute = value; }
      }
  
      /// &lt;summary&gt;
      /// Type of the underlying query source to get the attribute from.
      /// &lt;/summary&gt;
      public DirectoryAttributeType Type
      {
          get { return type; }
          set { type = value; }
      }
  }
  </code></pre>
  
  <p>So, I am populating my attributes for my LDAP Search with the Property's DirectoryAttributeAttribute::Name value.  If it's not specified, then I just use the Property's Type name.  So in essence, User.Username maps to "cn" and so forth.  </p>
  
  <p>I'm wondering what the best way is to do the reverse.  So if I get a LDAP result back that contains a field named "cn" how do I find the property that has a DirectoryAttributeAttribute.Name that equals "cn".  I am working on a foreach that gets the custom attributes for each property, but then I have to run that foreach for every field in the result set :(  Kind of cumbersome.  Can anyone think of a better way to do this?</p>
  
  <p>Here is the code for the function that determines the field name that a property is mapped to:</p>
  
  <pre><code>private string GetFieldName(System.Reflection.MemberInfo member)
  {
      DirectoryAttributeAttribute[] da = member.GetCustomAttributes(typeof(DirectoryAttributeAttribute), false) as DirectoryAttributeAttribute[];
      if (da != null &amp;&amp; da.Length != 0)
      {
          if (da[0].Type == DirectoryAttributeType.ActiveDs)
              throw new InvalidOperationException("Can't execute query filters for IADs* properties.");
          else
              return da[0].Attribute;
      }
      else
          return member.Name;
  }
  </code></pre>
  
  <p>Thanks,
  Chris</p>