views:

104

answers:

3

I have written a generic type: IDirectorySource<T> where T : IDirectoryEntry, which I'm using to manage Active Directory entries through my interfaces objects: IGroup, IOrganizationalUnit, IUser.

So that I can write the following:

IDirectorySource<IGroup> groups = new DirectorySource<IGroup>(); // Where IGroup implements `IDirectoryEntry`, of course.`

foreach (IGroup g in groups.ToList()) {
    listView1.Items.Add(g.Name).SubItems.Add(g.Description);
}

From the IDirectorySource<T>.ToList() methods, I use reflection to find out the appropriate constructor for the type parameter T. However, since T is given an interface type, it cannot find any constructor at all!

Of course, I have an internal class Group : IGroup which implements the IGroup interface. No matter how hard I have tried, I can't figure out how to get the constructor out of my interface through my implementing class.

[DirectorySchemaAttribute("group")]
public interface IGroup {
}

internal class Group : IGroup {
    internal Group(DirectoryEntry entry) {
        NativeEntry = entry;
        Domain = NativeEntry.Path;
    }
    // Implementing IGroup interface...
}

Within the ToList() method of my IDirectorySource<T> interface implementation, I look for the constructor of T as follows:

internal class DirectorySource<T> : IDirectorySource<T> {
    // Implementing properties...
    // Methods implementations...
    public IList<T> ToList() {
        Type t = typeof(T)

        // Let's assume we're always working with the IGroup interface as T here to keep it simple.
        // So, my `DirectorySchema` property is already set to "group".
        // My `DirectorySearcher` is already instantiated here, as I do it within the DirectorySource<T> constructor.
        Searcher.Filter = string.Format("(&(objectClass={0}))", DirectorySchema)

        ConstructorInfo ctor = null;
        ParameterInfo[] params = null;

        // This is where I get stuck for now... Please see the helper method.
        GetConstructor(out ctor, out params, new Type() { DirectoryEntry });

        SearchResultCollection results = null;

        try {
            results = Searcher.FindAll();
        } catch (DirectoryServicesCOMException ex) {
            // Handling exception here...
        }

        foreach (SearchResult entry in results)
            entities.Add(ctor.Invoke(new object() { entry.GetDirectoryEntry() }));

        return entities;            
    }
}

private void GetConstructor(out ConstructorInfo constructor, out ParameterInfo[] parameters, Type paramsTypes) {
    Type t = typeof(T);

    ConstructorInfo[] ctors = t.GetConstructors(BindingFlags.CreateInstance
                                                | BindingFlags.NonPublic
                                                | BindingFlags.Public
                                                | BindingFlags.InvokeMethod);

    bool found = true;

    foreach (ContructorInfo c in ctors) {
        parameters = c.GetParameters();

        if (parameters.GetLength(0) == paramsTypes.GetLength(0)) {
            for (int index = 0; index < parameters.GetLength(0); ++index) {
                if (!(parameters[index].GetType() is paramsTypes[index].GetType()))
                    found = false;
            }
            if (found) {
                constructor = c;
                return;
            }
        }
    }

    // Processing constructor not found message here...
}

My problem is that T will always be an interface, so it never finds a constructor.

Is there a better way than looping through all of my assembly types for implementations of my interface?

I don't care about rewriting a piece of my code, I want to do it right on the first place so that I won't need to come back again and again and again.

EDIT #1

Following Sam's advice, I will for now go with the IName and Name convention. However, is it me or there's some way to improve my code?

Thanks! =)

+3  A: 

You can loop through all classes in the assembly and find one that implements the interface. You'll need to decide what to do when you find multiple implementations.

Or if you have a consistent naming scheme, you can generate the class name from the interface name.

Sam
What do you mean by *can generate the class name from the interface name*? I guess I could not have `class IGroup` as well as having `interface IGroup`, if I understand correctly. Though it's pretty generic as code, I feel like there's a code smell somewhere. Do I approach my generic type the good way?
Will Marcouiller
Looping through the assembly types to look for the implementations of my interface seems a bit overkill for me. Would there be a better approach?
Will Marcouiller
@Will: Sam means something like if you have interface IName then if you are following the usual naming scheme the class name would be Name. So given interface IName you would just remove the I and have a class name.Of course you could go with another naming scheme if you would want to.
Patko
@Patko: Thanks for this explanation. That is always what I do, following the naming conventions as much as possible. Thanks! =)
Will Marcouiller
Looking through the assembly, or assuming a class of the same name (minus the I) will be there is clear sign of a flawed design. It wouldn't even solve the problem, because it would require that all possible `IGroup` are actually `Group` (which will never be true for any class derived from `IGroup` externally). A few questions. Is `IGroup` normally an empty interface? Why must `Group` be internal?
Mark H
@Mark H: Thanks for your comment. =) `IGroup` exposes all the required properties to easily manage a group entry. I make `Group` internal for such purpose as when I come to make some changes in my implementation, it won't break the code. I force the call to my library entry point methods to instantiate the my public interfaces. I'm currently using the Façade design pattern to ease the use of my library by others.
Will Marcouiller
The problem I see with this, is that any changes you do make to `Group` will never be reflected in other implementations of `IGroup`. You could solve this by using a `public abstract class Group` from which all other groups derive (rather than implementing IGroup directly). Abstract classes offer more flexibility for modifications without breaking derived classes. An interface can never change without breaking code (though can be extended with extension methods).
Mark H
+5  A: 

You have several possibilities here.

  • Sam gave you one answer.
  • Use some sort of a container, see Depencency injection.
  • Constrain the type T to have a default constructor (Constructor constraint) and add a SetEntry(DirectoryEntry) to the IDirectoryEntry interface.
  • Refactor your code so that your directory source is not burdened with creating new instances. You could maybe have different searchers, each returning correct type.

class DirectorySource<T>: IDirectorySource<T>  {   
  public DirectorySource(ISearcher<T> searcher) {
    Searcher = searcher;   
  }   
  public IList<T> ToList()    {
    string filter = "...";
    return Searcher.FindAll(filter);   
  } 
}     
class GroupSearcher: ISearcher<Group> {
  public IList<Group> FindAll(string filter)    {
    entries = ...
    var entities = new List<Group>();
    foreach (var entry in entries) 
      entities.Add(new Group(entry.GetDirectoryEntry());
    return entities;   
  } 
}

You would then instantiate you DirectorySource like this:

IDirectorySource<Group> groups = new DirectorySource<Group>(new GroupSearcher());
  • ... :)

EDIT: You could also use lambda expressions.

class DirectorySource<T>: IDirectorySource<T> {
  // Or you could put the parameter in constructor if this is not the only place
  // where you create new instances of T
  public IList<T> ToList(Func<DirectoryEntry, T> create) {
    ...
    foreach (var entry in entries)
      entities.Add(create(entry.GetDirectoryEntry()));
    return entities;
  }
}

IList<Group> groups = new DirectorySource<Group>().ToList(entry => new Group(entry));

And regarding class responsibilities and such, do you have special handling for each supported type in eg. Change(T) method (or any other)? If so then I would still refactor and use IDirectoryEntryManager<T> (or some other name) which would know how to handle appropriate type. DirectorySource could then use that class to manipulate concrete types and not be burdened with details that do not belong there.

Patko
The DI container is the best in my opinion.with ninject you can simply bind all the Types to the Interface and receive a list of them in your constructor.
Gnostus
@Patko: As I *must* have a `Searcher`, which is an instance of the `System.DirectoryServices.DirectorySearcher` class, within my `IDirectorySource<T>` generic interface, since I *must* be able to search for entries of any of the AD's schemas, wouldn't it be adviseable to wrap the `DirectorySearcher` within the generic type instead of doing it through an independant class? I don't get the pattern you're exposing me. Do you know about the Façade design pattern? For the sake of ease of use, there is only one entry point to the library that delivers every single feature of it through methods.
Will Marcouiller
Your approach seems clean though.
Will Marcouiller
@Will: What exactly is the responsibility of `IDirectorySource<T>`? Usually it is a good thing to design your classes so that every class has one responsibility, no more. That is called the single responsibility principle.So yes, maybe you should have GroupDirectorySource, maybe a DirectorySearcher wrapped in GroupSearcher, maybe something else. For now only you know what is the exact purpose of each class, we can only speculate.
Patko
@Patko: Thanks for these guidelines. The responsibility of `IDirectorySource<T>` is to manage: create, change, delete and list, an Active Directory entry, that is, a schema representing either a group, an user or an organizational unit. Each of these are managed through the `System.DirectoryServices.DirectoryEntry` class. Each of LDAP entry/entity are the quite the same as every property is available to to every schema. That is why I thought suitable to use a generic type: the `IDirectorySource<T>` interface. Shall I mention that I inspired myself from Bart de Smet who has written `Linq to AD`
Will Marcouiller
@Patko (continuing): The `IDirectorySource<T>` has the following methods in it: `ToList()`, `GetByUnit<T>(IOrganizationalUnit unit)`, `Persist(T entity)`, `Change(T entity)` and `Delete(T entity)`, just to name a few. Each of these can be applied to any of the `IGroup`, `IOrganizationalUnit` and `IUser`, as they're all considered entries for Active Directory. Then, I have attributes for both directory schema and attributes on top of each respective interface (schema) and properties (attributes). That said, I then only have to scan for the attributes to know what property to load from the AD.
Will Marcouiller
@Patko: I unfortunately don't have access to lambda expressions. In fact, I'm more proficient in .NET 3.5, but I *must* work with VS2005 and .NET 2.0, in addition to it, VBNET... That's definitely not my choice. There are things that one can do in .NET 2.0 C#, that can't be done in the same version VBNET. Thanks for your explicit enlightment. I am reconsidering my architecture and taking into account all that you have written. I plan to use the `Unity Application Block` for my dependency injection. What do you think of that? Have you any experience with the tool?
Will Marcouiller
@Will: Unfortunately no, I usually use StructureMap. But AFAIK most of these tools are ok, so you can hardly go wrong in picking either one. There are also plenty of comparisons between DI tools, including here on SO.
Patko
@Patko: IS there somewhere some kind of example of your approach that I could download the code sample so that I could even better understand all the concepts discussed within your excellent answer? I thank you for your support. God Bless SO! =) After all of your support, I shall promote your answer as the solution being, and upvote it to help your reputation here on SO. Thanks again! =)
Will Marcouiller
@Will: Thanks for the rep :) As for examples, much can be found on wikipedia (link in my answer above) and under "Further reading". You can also look at http://jamesshore.com/Blog/Dependency-Injection-Demystified.html or some other link. I also recommend reading something on so called SOLID principles (which DI is part of) which can be useful at times :)
Patko
+2  A: 

You can create special attribute to point implementing type without the necessity to rely on naming convention.

[AttributeUsage(AttributeTargets.Interface)]
public class ImplementingTypeAttribute: Attribute
{
    public Type ImplementingType { get; set; }

    public ImplementingTypeAttribute(Type implementingType)
    {
        ImplementingType = implementingType;
    }
}

But refactoring is great idea :)

Yury Tarabanko