3

I'm having a problem writing a generic method to retrieve AD Groups or Users with a parameter that can be one of two types - either System.DirectoryServices.AccountManagement GroupPrincipal or UserPrincipal

The method is as follows:-

private static IEnumerable<string> GetGroupsOrUsers<T>(T GroupOrUserPrincipal)
{
   PrincipalSearcher ps = new PrincipalSearcher();
   ps.QueryFilter = GroupOrUserPrincipal;

   etc.........
}

The problem is the GroupOrUserPrincipal is showing the following error:-

Cannot implicitly convert type 'T' to System.DirectoryServices.AccountManagement.Principal

Am I able to do this or am I missing something ?

Stecya
  • 22,896
  • 10
  • 72
  • 102
cyberbobcat
  • 1,169
  • 1
  • 18
  • 34
  • 3
    Quick question. Why don't you write one method for groups and another one for users? – Ignacio Soler Garcia Nov 09 '11 at 09:26
  • That's what I had done but just wanted to streamline it a bit using just one method - there is more code in this method so really it was to avoid duplication. – cyberbobcat Nov 09 '11 at 09:29
  • GroupPrincipal and UserPrincipal are derived from Principal? – Tudor Nov 09 '11 at 09:31
  • Couple of good answers pointing to a type constraint - but those will fail if you don't want your code to work for any other principal types, e.g. a ComputerPrincipal (i.e. did you mean that you want it to work for the two types you've listed, and no others?) – Damien_The_Unbeliever Nov 09 '11 at 09:34
  • @J. Kommer - my point was, the OP requested something that would work for `GroupPrincipal` and `UserPrincipal` - I was trying to ask whether that was an *exclusive* list of types that this method should work for... – Damien_The_Unbeliever Nov 09 '11 at 09:41
  • @Damien_The_Unbeliever Ah, apologies - I misread your original comment as can, not can't. (Suffer from dyslexia) – Johannes Kommer Nov 09 '11 at 09:44

4 Answers4

7

You should restrict T to types that your method makes sense for:

private static IENumerable<string> GetGroupsOrUsers<T>(T GroupOrUserPrincipal)
        where T : Principal
{
      // .....

That prevents calls of GetGroupsOrUsers<int>, and lets T be implicitly converted to Principal, fixing your error (or so I hope).

Jens
  • 25,229
  • 9
  • 75
  • 117
  • Very cool. Never thought about doing this. Do you know the Pro's and Con's of using this? – Jared Beach Feb 13 '14 at 13:47
  • @thats_how_i_feel: You can read more about this at http://msdn.microsoft.com/en-us/library/ms379564%28v=vs.80%29.aspx#csharp_generics_topic4. I don't know any cons, pros are mostly type safety and re-usability. – Jens Feb 13 '14 at 13:52
  • Well I like it. I feel like it encourages better object oriented programming. If you have three classes that all have a method that does essentially the same thing and you want to make another method in another class that utilizes their similar methods, you shouldn't have to make three new methods, right? Anyways, [this section of Wikipedia's C# page](http://en.wikipedia.org/wiki/C_Sharp_syntax#Type-parameters) helped me understand type parameters better. – Jared Beach Feb 13 '14 at 15:29
2

You need to specify a type parameter constraint; for example:

private static IEnumerable<string> GetGroupsOrUsers<T>(T GroupOrUserPrincipal) where T: Principal

This limits the classes that can be used as T to only classes of type Principal or a subclass of Principal. The C# compiler then knows that everything passed to GetGroupsOrUsers(...) will be of a type compatible with Principal and will no longer error.

Johannes Kommer
  • 6,401
  • 1
  • 39
  • 45
2

Possibly you want to look at Generic Contraints in particular a derivation contraint where your various T objects all impliment a given interterface. Eg

where T : Principle
Ricibob
  • 7,505
  • 5
  • 46
  • 65
0

You have to write a cast in this line:

ps.QueryFilter = (Principal) GroupOrUserPrincipal; 
Fischermaen
  • 12,238
  • 2
  • 39
  • 56