Hey All,
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.
I do the reverse part by assigning custom attributes to the properties of the class that are the actual names of the database fields.
Here is an example of the class, as well as the custom attribute (the DirectorySchemaAttribute
and DirectoryRootAttribute
implementations are not included... those pieces are working correctly):
[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; }
}
/// <summary>
/// Specifies the underlying attribute to query for in the directory.
/// </summary>
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)]
public class DirectoryAttributeAttribute : Attribute
{
private string attribute;
private DirectoryAttributeType type;
/// <summary>
/// Creates a new attribute binding attribute for a entity class field or property.
/// </summary>
/// <param name="attribute">Name of the attribute to query for.</param>
public DirectoryAttributeAttribute(string attribute)
{
this.attribute = attribute;
this.type = DirectoryAttributeType.Ldap;
}
/// <summary>
/// Creates a new attribute binding attribute for a entity class field or property.
/// </summary>
/// <param name="attribute">Name of the attribute to query for.</param>
/// <param name="type">Type of the underlying query source to get the attribute from.</param>
public DirectoryAttributeAttribute(string attribute, DirectoryAttributeType type)
{
this.attribute = attribute;
this.type = type;
}
/// <summary>
/// Name of the attribute to query for.
/// </summary>
public string Attribute
{
get { return attribute; }
set { attribute = value; }
}
/// <summary>
/// Type of the underlying query source to get the attribute from.
/// </summary>
public DirectoryAttributeType Type
{
get { return type; }
set { type = value; }
}
}
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.
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?
Here is the code for the function that determines the field name that a property is mapped to:
private string GetFieldName(System.Reflection.MemberInfo member)
{
DirectoryAttributeAttribute[] da = member.GetCustomAttributes(typeof(DirectoryAttributeAttribute), false) as DirectoryAttributeAttribute[];
if (da != null && 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;
}
Thanks, Chris