You are searching for an interface using
the Type
class. However, complex interface
searches are not available through the
GetInterface
and
GetInterfaces
methods of a Type
object. The GetInterface
method searches for an
interface only by name (using a case-sensitive or -insensitive
search), and the GetInterfaces
method returns an
array of all the interfaces implemented on a particular type. You
want a more focused searching mechanism that might involve searching
for interfaces that define a method with a specific signature or
implemented interfaces that are loaded from the Global Assembly Cache
(GAC). You need more flexible and more advanced searching for
interfaces that does not involve creating your own interface search
engine.
The FindInterfaces
method of a Type
object can be used along with a
callback to perform complex searches of interfaces on a type. The
following method will call a custom interface searching method,
SearchInterfacesOfType
:
using System; using System.Reflection; public class SearchType { public void FindSpecificInterfaces( ) { Type[] names = new Type[3] {Type.GetType("System.ICloneable"), Type.GetType("System.Collections.ICollection"), Type.GetType("System.IAppDomainSetup")}; Type[] interfaces = SearchInterfacesOfType(Type.GetType( "System.Collections.ArrayList"), names); if (interfaces.Length > 0) { Console.WriteLine("Matches found:"); for(int counter =0; counter < interfaces.Length; counter++) { Console.WriteLine(" IFace Name: " + interfaces[counter].ToString( )); Console.WriteLine(" IFace Base Type: " + interfaces[counter].BaseType); foreach (object attr in interfaces[counter].GetCustomAttributes(false)) { Console.WriteLine(" IFace attr: " + attr.ToString( )); } } } else { Console.WriteLine(" No matches found"); } } public Type[] SearchInterfacesOfType(Type searchedType, Type[] ifaceNames) { TypeFilter filter = new TypeFilter(IfaceFilterCallback); Type[] interfaces = searchedType.FindInterfaces(filter, ifaceNames); return (interfaces); } public bool IfaceFilterCallback(Type type, object criteria) { foreach (Type ifaceName in (Type[])criteria) { if(type.FullName == ifaceName.FullName) { return (true); } } return (false); } }
The
FindSpecificInterfaces
method searches for any of
the three interface types, contained in the Names
array that are implemented by the
System.Collections.ArrayList
type.
The
SearchinterfacesOfType
method accepts a type
(searchedType
) on which to search for
interfaces and an object (ifaceNames
) that
contains criteria for the search. For this method, the criterion is a
Type
array of interfaces. This method then calls
the FindInterfaces
method on the
searchedType
parameter and passes in a
delegate and the Type
array criteria of
interfaces. (The delegate will be called back to for each found
interface.) This method then returns an array of interface types that
match the criterion.
The
TypeFilter
delegate, filter
,
defines the IfaceFilterCallback
method to be
called for each interface found on the
searchedType
object. The real power of
this search mechanism lies in the
IfaceFilterCallback
callback method.
This callback searches for each of the interface types in the
criteria
array that is implemented by the
searchedType
parameter of the
SearchInterfacesOfType
method.
Most complex member searches can be performed only through the use of
the
FindInterfaces
method
of a Type
object. This method makes use of the
TypeFilter
delegate, which is passed to the filter
parameter. This delegate is supplied by the FCL and allows an extra
layer of filtering (of any type that you want) to occur. This
delegate returns a Boolean value, where true
indicates that the ifaceType
object passed
to this delegate should be included in the Type
array that the FindInterfaces
method returns;
false
indicates that this
ifaceType
object should not be included.
The FindInterfaces
method will take into account
all interfaces implemented by the type being searched as well as all
of its base types when performing a search. In addition, if any of
the interfaces implemented by any of these types also implements one
or more interfaces, those interfaces are included in the search.
There are many ways to use this TypeFilter
delegate to search for interfaces implemented on a type—here
are just a few other searches that can be performed:
A filter to search for all implemented interfaces that are defined
within a particular namespace (in this case, the
System.Collections
namespace):
public bool IfaceFilterCallback(Type type, object criteria) { if (type.Namespace.Equals("System.Collections")) { return (true); } else { return (false); } }
A filter to search for all implemented interfaces that contain a
method called Add
, which returns an
Int32
value:
public bool IfaceFilterCallback(Type type, object criteria) { if (type.GetMethod("Add") != null && type.GetMethod("Add").ReturnType == Type.GetType("System.Int32")) { return (true); } else { return (false); } }
A filter to search for all implemented interfaces that are loaded from the Global Assembly Cache (GAC):
public bool IfaceFilterCallback(Type type, object criteria) { if (type.Assembly.GlobalAssemblyCache) { return (true); } else { return (false); } }
A filter to search for all implemented interfaces that are defined within an assembly with the version number 1.0.3300.0:
public bool IfaceFilterCallback(Type type, object criteria) { if (type.Assembly.FullName.IndexOf("Version=1.0.3300.0") >= 0) { return (true); } else { return (false); } }
See Recipe 7.8; see the “Delegate Class” and “Type.FindInterfaces Method” topics in the MSDN documentation.