Saturday, March 17, 2012

LINQ To LDAP: 2.5

Been a while since my last post. There are quite a few changes in 2.5, but I want to focus on the biggest ones.

Multiple Naming Contexts and Configurations
First big change is now you can query for mapped objects in any naming context. This makes it easier to reuse a mapping for different parts of the directory or even with a completely different directory. The naming context you specify here will always override whatever you have mapped.
context.Query<User>(namingContext: "naming context");

This leads me to the next change. I've had a lot of questions about having dynamic configurations and multiple directory support. I decided to give you more control over the lifespan of LdapConfiguration. I've also exposed DirectoryMapper so you can share your mappings among multiple configurations. Each configuration has it's own connection factory so this should handle connecting to multiple directories.

You can store your configurations with your favorite IoC container, in a static class, or whatever your preference. You can still use a single global one by calling UseStaticStorage on the configuration.

Custom Mapping
I've also added support for mapping properties to custom values. There's a new method on ClassMap called MapCustom. Here's an example of mapping ObjectGuid as a custom property:
MapCustom(s => s.ObjectGuid).Named("objectGuid")
    .ConvertFromDirectoryUsing(d =>
                                    {
                                        var bytes = d.GetValues(typeof(byte[]))[0] as byte[];
                                        return new Guid(bytes);
                                    })
    .ConvertToFilterUsing(v => v.ToStringOctet())
    .ConvertToDirectoryUsing(v => v.ToByteArray())
    .CompareChangesUsing((guid1, guid2) => guid1.Equals(guid2));
At a minimum you have to implement ConvertFromDirectoryUsing. If you want to filter by it you have to implement ConvertToFilterUsing. And if you want to update the property then you have to implement ConvertToDirectoryUsing. CompareChangesUsing is optional. If you've implemented IDrectoryObject or subclassed DirectoryObjectBase and your custom mapping is for something that can't really use the default Equals implementation then you'll want to implement it.

I've also added support for forwarding values in place of others. Right now it's only available when mapping DateTimes (due to the 9223372036854775807 value meaning "not set"). I plan to expand this to other property types if necessary. Here's how you use it:
Map(c => c.AccountExpires)
    .Named("accountExpires")
    .DateTimeFormat(null)
    .DirectoryValue("9223372036854775807").Returns(null)
    .InstanceValue(DateTime.MinValue).Sends("9223372036854775807")
    .InstanceValueNullOrDefault().Sends("9223372036854775807");

Querying
I just want to add a small note about the Filter class. Previously I was escaping any special characters you passed in. I think now that I should give you more control over the values. You can now use Filter.Equal("attribute", "*"). However, if you want to escape any special characters you can use Filter.Equal("attribute", "some value".CleanFilterValue()).

You can read more about what's in this release here.

No comments:

Post a Comment