Unit Testing, Agile Development, Leadership & .NET - By Roy Osherove
Try that on B.
Class A
Protected Overridable Sub Foo()
End Sub
End Class
Class B : Inherits A
Protected NotOverridable Overrides Sub Foo()
You need to be looking at the interface mapping if you really want to be certain.
Bill is right, you can't use the code you've shown above, you have to use interface mapping.
Your code will show any sealed private method declared by the class.
You have to call Type's FindInterfaces method. Using interfaces you have to call GetInterfaceMap on each of the retrieved interfaces, and then check if the method that is implementing interface is private. Pretty simple :)
so something like this:
foreach (var anInterface in GetType().FindInterfaces()){
var mapp = GetType().GetInterfaceMap(anInterface);
foreach(var info in mapp.TargetMethods){
if (info.IsPrivate)
{
Console.WriteLine("Explicit interface implementation: {0}", info.Name);
}
I can't shake the feeling that this can go wrong in some situations, or that it's only coincidentally correct. If I had to find explicit implementations, I'd go with something like this:
def FindExplicitImplementations(type as Type):
for interfaceType in type.GetInterfaces():
for method in type.GetInterfaceMap(interfaceType).TargetMethods:
yield method unless method.IsPublic
Mihailo: There is no such thing as a private sealed method that you can create manually - it will not compile (method has to override another method in order to be able to be sealed)
Also: Calling "GetInterfaceMap" when the interface is not explicitly used in the class - throws an exception.
Hi Roy,
a) you're right, I wanted to concur with Bill, sorry to lead you wrong way.
b) what do you mean by that?
I used this code, and it worked fine, try copy paste and see if it works for you:
foreach (var anInterface in typeof(Class1).FindInterfaces((type,criteria)=> true, ""))
var mapp = typeof(Class1).GetInterfaceMap(anInterface);
foreach (var info in mapp.TargetMethods)
Explicit interface implementations aren't necessarily private unless the language is C#. In VB for example all interface implementations are explicit and can have any scope. So if you're not sure that the class you're reflecting on is written in C# as far as I can see.
Pingback from Dew Drop - October 16, 2008 | Alvin Ashcraft's Morning Dew
This code is still only useful for C#. With VB the interface implementation can be explicitly mapped to public members with different names.
As I said earlier, the correct way is to use GetInterfaceMap. I have not seen that throw exceptions for C#'s implicit implementation. Can you post an example of when it throws an exception ? thanks.
Pingback from Arjan`s World » LINKBLOG for October 16, 2008
Did you get the code I've sent you? The first comment had a general idea how to do it, for the second one I actually wrote a console application to test your scenario, but I don't see my second comment in the list.
Cheers,
Mihailo
This solution works for VB.NET and C# code
Bill: yes this will also work on VB.NET since in VB.NET to make an EXPLICIT interface implementation, you need to make the method private (so that only casting to the interface shows it)
for example the following private method :
Private Sub Write(ByVal input As String) Implements ILogger.Write
Mihailo: you are right: I could not recreate that exception so your solution works as well. however, it has a loop within a loop so I'm not sure if it is as simple as mine is.
All interface implementations in VB are explicit, Private, Protected, Friend and Public alike. Take the following class "SomeClass" where a public method explicitly implements two interface methods as an example. Your method would not find this.
Public Interface ISomeInterface
Function Foo() As String
Function Bar() As String
End Interface
Public Class SomeClass
Implements ISomeInterface
Public Overrides Function ToString() As String Implements ISomeInterface.Foo, ISomeInterface.Bar
Return "Hello world!"
End Function
Roy,
In VB today *All* interface implementation is Explicit. I could have:
Public Sub Close() Implements IDisposable.Dispose()
Or I could make that Protected or Private. In all cases with VB you can call the method directly from in the same type. C# on the other hand forces a naming pattern on their interface mapping that forces you to cast to the interface because the method name is illegal to call form the C# compiler. Once you have the method info though you can always invoke.
I think the problem here is what you are calling "explicit". I think I discussed this with you before, there's really only two types of interface implementation as far as IL and the CLR are concerned, mapped or implicit. VB doesn't at present have the implicit but it does have the full mapping as the CLR sets out. C# on the other hand has implicit but only limited mapping.
I'm guessing the confusion here is this arbitrary definition of what you are calling "explicit" is a C# implementation thing only, not a CLR or a VB requirement. As there are only two kinds of implementation at CLR level, when you say "explicit" that to me means you mean the other one than "implicit". But it seems you mean something else ?
Bill: Nope, I think you're right and I misunderstood the "Explicit" and thought that VB had that same feature in its compiler when in fact it's even more powerful in terms of mapping.
That's pretty cool. I learned something!
Thanks Roy :) It's not that common for VB to actually have a more complete CLR implementation than C#, although it does in a few places such as custom Events have the Raise (or fire block) and optional parameters, but usually people think it's C# defines the CLR or is the complete implementation. IL/CLR is actually more powerful than the two, jsut a real pain to write <g>
BTW: if this is for test code spits, I'd rather have the tests spit out a test of an interface (ideally, where possible re-use standard tests for that interface and treat NotSupported exceptions as a pass)