Search code examples
c#active-directoryinversion-of-controlfactory-pattern

IoC and Microsoft classes


I'm new to using an Ioc, and am wondering how, if at all, I should be injecting Microsoft classes. Specifically, I am using DirectorySearcher. Can I inject this? I don't think so.

So I made a wrapper class for DirectorySearcher, and created a factory method. So I could inject my wrapper class where I needed it, and call the factory 'Create' method. Is this the way to handle this type of situation? Or do I need a whole Factory class?

public class Directory
{
    public Directory() { }
    public static Directory Create(string userName, string password, string ldapPath)
    {
        var entry = new DirectoryEntry(path, userName, password, AuthenticationTypes.Secure);
        var searcher = new DirectorySearcher(entry);
        return new Directory() { Searcher = searcher }; 
    }
}

My concern is that my wrapper is tightly coupled to DirectorySearcher. To test, I really need to access my live AD.


Solution

  • According to Agile Principles, Patterns, and Practices:

    clients [...] own the abstract interfaces

    What it means is that you should define the interface in a way it makes sense for the consumer; not the target. Others call this concept ports and adapters, where the port is the abstraction that is used by the application and the adapter is the implementation of that interface that translates the calls to the external system (LDAP in your case).

    So although you can create an 'adapter' that allows you to create an directory using LDAP, your implementation is leaking implementation details, such as the fact that you need certain credentials and the fact that you need to supply an ldapPath. These are violations of the Dependency Inversion Principle, because:

    Abstractions should not depend on details.

    So instead, try to find out what the abstraction is for your application. You might want to define the abstraction on a much higher level. For instance, it's highly unlikely that creating the directory is actually the use case that the user wants to perform. Instead, the use case might be something like creating a new user account and to accomplish that, one of the steps in that use case is to create a directory.

    So think about what your application needs, and prevent specifying any details in that. But to be honest, this can be really hard. It took me quite some practice to be able to do that, and I still get my abstractions wrong the first time most of the time. The trick is to be able to accept that you were wrong and improve the design. One step at a time.

    So how your design should really look like, I don't know. I have no idea what you are trying to accomplish and even if I knew, I would probably still give you the wrong advice. But one thing I know, creating a factory is usually not the solution. It just moves the problem. Don't get me wrong, the factory is still a valid design pattern, but you won't need them that often if you are applying the SOLID principles and Dependency Injection correctly.