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