Constructor constraint on generic types or simply check for constraint within my generic type constructor?
I have a generic class DirectorySource<T>
which depends on an interface IDirectorySearch<T>
.
Both are generics and have the same type constraint:
public class DirectorySource<T> where T : IDirectoryEntry { }
public interface IDirectorySearcher<T> where T : IDirectoryEntry { }
So, for instance, when I want a source to manipulate groups, I would go this way:
IDirectorySearcher<Group> groupSearcher = new GroupSearcher(ROOT, SCOPE);
IDirectorySource<Group> groups = new DirectorySource(groupSearcher);
What I wish to come up with is to force, when my generic type DirectorySource<T>
is of DirectorySource<Group>
type, that my searcher is a GroupSearcher
, and I don't want one to be able to pass in a UserSearcher
, for example.
I have read the following articles:
- C#: Generic types that have a constructor?;
- An Introduction to C# Generics;
- new Constraint (C# Reference).
And I don't seem to get how to handle this kind of constraint with my class. As for now, I have the following:
public class DirectorySource<T> where T : IDirectoryEntry {
public DirectorySource(IDirectorySearcher<T> searcher) {
Searcher = searcher;
}
public IDirectorySearcher<T> Searcher { get; private set; }
}
And then, I have the following too:
public class GroupSearcher : IDirectorySearcher<Group> {
public GroupSearcher(DirectoryEntry root, SearchScope scope) {
NativeSearcher = new DirectorySearcher();
NativeSearcher.SearchRoot = root;
NativeSearcher.SearchScope = scope;
}
// Implementing interface...
}
I can't just replace the Searcher
property type, as this would cause my generic class to become non-generic.
Any idea or something I didn't understand correctly about this constructor constraint on how I should go with what I want to accomplish?
EDIT #1
The reason I want to do so is because one could do the fo开发者_如何学JAVAllowing:
IDirectorySearcher<User> userSearcher = new UserSearcher(ROOT, SCOPE);
IDirectorySource<Group> groups = new DirectorySource<Group>(userSearcher);
This seems incorrect to me...
1. Am I missing something obvious here? =)
Thanks in advance!
What I wish to come up with is to force, when my generic type DirectorySource is of
DirectorySource<Group>
type, that my searcher is a GroupSearcher.
Why? That's going against the point of encapsulating the searcher functionality into an interface, surely? You shouldn't care what the implementation is, so long as it can search for the right kinds of entry.
I don't think constructor constraints are really relevant here - that would only allow you to create a new instance of T
with no arguments...
EDIT: I can't see how your proposed problem is actually a problem. Let's look at the code:
IDirectorySearcher<User> userSearcher = new UserSearcher(ROOT, SCOPE);
IDirectorySource<Group> groups = new DirectorySource<Group>(userSearcher);
So here the T
for DirectorySource<T>
is Group
. Now the constructor will require you to pass in an IDirectorySearcher<Group>
- which userSearcher
isn't, as far as I can see. So this code wouldn't compile, which is what you want. Where's the problem?
Have you considered:
public class DirectorySource<TValue, TSearcher>
where TValue : IDirectoryEntry
where TSearcher : IDirectorySearcher<T>, new()
{
public DirectorySource(TSearcher seacher)
{
Searcher = seacher
}
public TSearcher Searcher { get; private set; }
}
IDirectorySearcher<Group> groupSearcher = new GroupSearcher(ROOT, SCOPE);
var groups = new DirectorySource<Group, GroupSearcher>(groupSearcher);
I think the only way you're going to get what you want (as I understand it) is if you add a GetSource
method to IDirectorySearcher
which returns an implementation of IDirectorySource<T>
.
精彩评论