"is" operator returning false when should be true?

D

Derrick

Hello all;

Since I do have working code, this is more for my curiosity only.

I'm creating a "Plugin" architecture, following some of the many examples on
the 'net. Basically what I have is this:
- a DLL which contains the interface that every plugin must implement
(IPlugin). This DLL also contains a class with the ability to search for
DLLs in the calling applications working directory that contain classes
implementing IPlugin (I call this the PluginLoader). I fixed the version of
this DLL to 1.0.0.0, so the version doesn't change everytime it's built.
- a DLL which contains a class that implements IPlugin, called MyPlugin.
This obviously references the IPlugin DLL.
- a test EXE which tries to load a plugin. Again, this obviously references
the IPlugin dll.

All the references are to the Projects within VS.NET, not to the DLLs.

As you can assume, there was a function in the PluginLoader as follows:

private Type[] SearchDirectoryForPlugins(string path)

{

string[] dlls = Directory.GetFiles(path, "*.dll");

ArrayList pluginList = new ArrayList();

foreach(string dll in dlls)

{

try

{

Assembly a = Assembly.LoadFile(dll);

Type[] types = a.GetTypes();

foreach(Type t in types)

{

if (t is FullNamespace.IPlugin)

{

pluginList.Add(t);

}

}

}

catch(Exception e) //should handle specific exception

{

Console.WriteLine(e.Message);

//the dll wasn't a valid .NET assembly. Ignore.

}

}

return (Type[]) pluginList.ToArray(typeof(Type)); //confusing, but I
like arraylists!

}


My problem was that the "if (t is FullNamespace.IPlugin)" line was returning
false when it encountered a class that does indeed implement IPlugin, and I
had no idea why. I have since changed the code, removing the "is", and now
using the Type.FindInterfaces function - which works perfectly.

Would anyone have any idea why "is" would not work as expected in this
scenario, when FindInterfaces works fine??

Thanks,

Derrick
 
J

Jonathan Allen

if (t is FullNamespace.IPlugin)

This line is asking if t, an object of type System.Type, implements
FullNamespace.IPlugin. You don't really care if System.Type implements
FullNamespace.IPlugin, what you care about is the type t represents.
 
N

Nicholas Paldino [.NET/C# MVP]

Derrick,

You might want to check the fusion logs here to see what assemblies are
being loaded in your app. It sounds like there might be different versions
of the plugin assembly being loaded (for one reason or another), and as a
result, the call to is is not returning what you expect.

Also, you might want to try removing the reference and then re-adding it
in your plugin project, this might help.

Hope this helps.
 
I

Ignacio Machin \( .NET/ C# MVP \)

Hi,

It's correct

t is instance of Type , as you can imagine Type do not implement IPlugin,
and is correct in returning false.

The thing that t has information about a class that does implement IPlugin
is not know.

That is why Type expose GetInterface method

cheers,
 
D

Derrick

Thanks. What you and Jonathon have said does indeed make sense. I had
assumed that even though I had cast the object to a System.Type, the "is"
operator would still return True because the object still carries along all
the IPlugin "meta data" (for lack of a better term).

I guess I assumed wrong!

As I said in the OP, my code works just fine with the Type.FindInterfaces,
so I'll just leave it. I would have prefered to use "is" because it is much
cleaner.

Thank again,

Derrick


Ignacio Machin ( .NET/ C# MVP ) said:
Hi,

It's correct

t is instance of Type , as you can imagine Type do not implement IPlugin,
and is correct in returning false.

The thing that t has information about a class that does implement IPlugin
is not know.

That is why Type expose GetInterface method

cheers,

--
Ignacio Machin,
ignacio.machin AT dot.state.fl.us
Florida Department Of Transportation





Derrick said:
Hello all;

Since I do have working code, this is more for my curiosity only.

I'm creating a "Plugin" architecture, following some of the many examples
on the 'net. Basically what I have is this:
- a DLL which contains the interface that every plugin must implement
(IPlugin). This DLL also contains a class with the ability to search for
DLLs in the calling applications working directory that contain classes
implementing IPlugin (I call this the PluginLoader). I fixed the version
of this DLL to 1.0.0.0, so the version doesn't change everytime it's
built.
- a DLL which contains a class that implements IPlugin, called MyPlugin.
This obviously references the IPlugin DLL.
- a test EXE which tries to load a plugin. Again, this obviously
references the IPlugin dll.

All the references are to the Projects within VS.NET, not to the DLLs.

As you can assume, there was a function in the PluginLoader as follows:

private Type[] SearchDirectoryForPlugins(string path)

{

string[] dlls = Directory.GetFiles(path, "*.dll");

ArrayList pluginList = new ArrayList();

foreach(string dll in dlls)

{

try

{

Assembly a = Assembly.LoadFile(dll);

Type[] types = a.GetTypes();

foreach(Type t in types)

{

if (t is FullNamespace.IPlugin)

{

pluginList.Add(t);

}

}

}

catch(Exception e) //should handle specific exception

{

Console.WriteLine(e.Message);

//the dll wasn't a valid .NET assembly. Ignore.

}

}

return (Type[]) pluginList.ToArray(typeof(Type)); //confusing, but I
like arraylists!

}


My problem was that the "if (t is FullNamespace.IPlugin)" line was
returning false when it encountered a class that does indeed implement
IPlugin, and I had no idea why. I have since changed the code, removing
the "is", and now using the Type.FindInterfaces function - which works
perfectly.

Would anyone have any idea why "is" would not work as expected in this
scenario, when FindInterfaces works fine??

Thanks,

Derrick
 
M

Mark Rockmann

if (t is FullNamespace.IPlugin)
{
pluginList.Add(t);
}

The above block should be changed to:

<code>
if (typeof(FullNamespace.IPlugin).IsAssignableFrom(t))
{
// add the plugin type
pluginList.Add(t);
}
</code>

Mark
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top