Getting the constructor of an Interface Type through reflection, is there a better approach than loo

Posted by Will Marcouiller on Stack Overflow See other posts from Stack Overflow or by Will Marcouiller
Published on 2010-06-17T17:57:28Z Indexed on 2010/06/17 18:33 UTC
Read the original article Hit count: 365

Filed under:
|
|
|

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! =)

© Stack Overflow or respective owner

Related posts about c#

Related posts about generics