views:

153

answers:

5

I need to know if a Type implements an interface.

 Dim asmRule As System.Reflection.Assembly = System.Reflection.Assembly.LoadFrom(System.IO.Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Rule.dll"))

 For Each typeAsm As System.Type In asmRule.GetTypes
     If TypeOf typeAsm Is Rule.IRule Then
       'that does always return false even though they implement IRule'
     End If
 Next

Thanks to all. Now i know why typeof didn't work. The type naturally does not implement IRule. I have filtered out two options from your answers:

  1. GetType(Rule.IRule).IsAssignableFrom(typeAsm)
  2. typeAsm.GetInterface(GetType(Rule.IRule).FullName) IsNot Nothing

What is the better choise according to performance?

UPDATE: i've found out that it might be better to use:

Not typeAsm.GetInterface(GetType(Rule.IRule).FullName) Is Nothing

instead of

GetType(Rule.IRule).IsAssignableFrom(typeAsm)

because the Interface IRule itself is assignable of IRule what raises a MissingMethodExcpetion if i try to create an instance:

ruleObj = CType(Activator.CreateInstance(typeAsm, True), Rule.IRule)

UPDATE2: Thanks to Ben Voigt. He convinced me that IsAssignableFrom in combination with IsAbstract might be the best way to check if a given type implements an interface and is not the interface itself (what throws a MissingMethodException if you try to create an instance).

If GetType(Rule.IRule).IsAssignableFrom(typeAsm) AndAlso Not typeAsm.IsAbstract Then
+2  A: 

You want Type.IsAssignableFrom

Ben Voigt
Or Type.isSubclassof
rerun
@rerun: What part of **I need to know if an object implements an interface.** was unclear?
Ben Voigt
@Ben: The fact that the code in the question clearly doesn't match up with the text?
Jon Skeet
`TryCast` isn't what he's trying to do.
SLaks
@Jon: Sure looks to me like `IRule` is an interface.
Ben Voigt
@Ben then you can use Type/GetInterface()
rerun
Thank you for the answer and clarifying that IsAssignableFrom combinated with IsAbstract might be the best way(see Update2).
Tim Schmelter
@Tim: I think you missed the point of my `IsAbstract` suggestion. You want to exclude not only `IRule` itself, but any interfaces derived from `IRule`, and any abstract classes implementing `IRule`, because using `Activator.CreateInstance` will fail for these as well. Note that `CreateInstance` can fail for other reasons as well (you can't use it on a generic type pattern -- test with `ContainsGenericParameters`, or if there's no default constructor).
Ben Voigt
@Ben: No, i think i well understood your point. I want to create instances of IRule only for classes and not for instances or abstract classes. Therefor `IsAbstract` works perfectly. The other fail reasons are negligible because they could never happen in my situation.
Tim Schmelter
@Tim: ya, you got it. BTW if you're concerned about efficiency, swap the AndAlso to put the `IsAbstract` test in front, then the `IsAssignableFrom` check won't even be attempted for interfaces and abstract classes.
Ben Voigt
@Ben: There is only one interface(IRule) in Rule.dll, hence the check for IsAssignableFrom is deciding in almost all cases and the swap wouldn't change anything.
Tim Schmelter
+2  A: 

Another option:

If myType.GetInterface("Rule.IRule") IsNot Nothing Then

http://www.hanselman.com/blog/DoesATypeImplementAnInterface.aspx

AdamH
Thanks for this working answer. This is the best way (for me) because it besides avoids creating an instance of IRule itself. That is the problem with IsAssignableFrom. But i anyway choose Jon's answer because his answer is elaborated best.
Tim Schmelter
+4  A: 

In C#:

x is Class1 

in VB.NET:

TypeOf x Is Class1

Described here.

Steve_
Figured I'd refresh before I posted and bang, here was the correct answer. +1
Randolpho
This answer is correct but will not do what he's trying to do.
SLaks
Wow, I should have probably read the question better. I guess I am guilty of that rushed response syndrome I find so annoying about this site...
Steve_
Steve_ : I fixed the question to not be so misleading. Your answer, however, is incorrect for either question.
Gabe
+6  A: 

TypeOf ... Is works fine with inheritance:

Imports System

Public Class Test

    Public Shared Sub Main()
        Dim o As Object = 5

        If TypeOf o Is IFormattable Then
            Console.WriteLine("Yes")
        End If
    End Sub    

End Class

That works the same way as "is" in C#.

However, in your example, that's trying to see whether System.Type (or whatever subclass is actually used) implements Rule.IRule. That won't work... because you're not interested in whether System.Type implements the interface, you're interested in whether the instance of System.Type that the typeAsm variable refers to implements IRule.Rule.

In other words, your code wouldn't have worked any better in C# either. You need Type.IsAssignableFrom when talking about an instance of System.Type:

If GetType(Rule.IRule).IsAssignableFrom(typeAsm) Then
Jon Skeet
What is the better choice(see my update): using IsAssignableFrom or myType.GetInterface("Rule.IRule") IsNot Nothing? Thanks.
Tim Schmelter
@Tim: Personally I'm more of a fan of IsAssignableFrom just because it's already asking a Boolean question - and it's applicable in other situations. Don't sweat over it though :)
Jon Skeet
@Jon: i've found out that it might be better (in my situation) to use: Not typeAsm.GetInterface(GetType(Rule.IRule).FullName) Is Nothing. Because the Interface IRule itself is assignable from IRule. That causes an Missing MethodException if i try to create an instance with: ruleObj = CType(Activator.CreateInstance(typeAsm, True), Rule.IRule).
Tim Schmelter
@Tim: `GetInterface` is no better, because an abstract class can implement an interface. You need to check `IsAbstract`. It's also better to use the type cookie rather than the name whenever possible.
Ben Voigt
@Ben: Thanks for the IsAbstract tip :)
Tim Schmelter
+2  A: 

You're using the wrong keyword.

The C# is keyword, and VB.Net's TypeOf ... Is ..., will check whether the instance is of a type that implements the interface.
Therefore, your code will check whether the typeAsm variable, which is a System.Type instance, implements the IRule interface.
Since the System.Type class doesn't implement IRule, it will always return False.

You are actually trying to check whether the type represented by the System.Type instance implements IRule.
To do that, you need to use the methods in the System.Type class.

For example:

 If typeAsm.GetInterface(GetType(Rule.IRule)) IsNot Nothing Then
SLaks
`typeAsm.GetInterface(GetType(Rule.IRule).FullName) IsNot Nothing` is the correct way because GetInterface needs the Name as String. But thanks anyway.
Tim Schmelter
@SLaks: `GetInterface` doesn't accept a `System.Type`, so your code snippet doesn't work. Using the type name as a string is somewhat fragile and inefficient. I really do think that calling `IsAssignableFrom` is the optimal way.
Ben Voigt