Plugin Architecture Problem

  • Thread starter Thread starter Guest
  • Start date Start date
G

Guest

Hi,

[ BTW I'm using C# ]

I'm trying to implement a Plugin architecture where I have a single UI
framework, and then load dll components into that framework.

At the moment I'm constructing the Plugin loading mechanism, I've created a
plugin interface ( that the plugin clients must implement ) and a pluginhost
interface ( thart the ui framework plugin manager must imlpement ).

When the UI framework loads the plugin assembly it checks the types in the
assembly to ensure it supports the plugin interface, if it does then it
constructs an instance of this type and casts it to the plugin interface type.

If I create a source file with these interfaces in and link this file ( i.e.
share the file )into each project then I get a CastException - in
CreatePluginInstance - when I cast to the plugin interface type. If I
implement this interface in a separate dll and then reference this in the
framework and the pluginclient, then the cast succeeds.

I suppose this works, but I would rather keep the number of dlls to a
minimum, and hoped to be able to get away with just sharing the interface
source file. Is this possible ??, or do I need to implement it this way ??

regards
Rich.


CODE:

Interface.....

namespace PluginInterface
{
public interface IPlugin
{
IPluginHost Host{ get;set; }
}

public interface IPluginHost
{
bool Register(IPlugin ipi);
}
}


PluginCreation and Cast...

Assembly objAssembly = Assembly.LoadFrom(_strPath);

foreach (Type iterTypes in objAssembly.GetTypes())
{
foreach (Type iterInterfaces in
objIterGetAssemblyTypes.GetInterfaces())
{
if
(iterInterfaces.Equals(typeof(PluginInterface.IPlugin)))
{
CreatePluginInstance(iterInterfaces);
}
}
}
}

public void CreatePluginInstance( Type _assemblyType )
{
PluginInterface.IPlugin sui_Plugin =
(PluginInterface.IPlugin)Activator.CreateInstance(_assemblyType);
}
 
You can define the interface in a single assembly but you need to manage how
many copies of it are floating around. What's probably happening is that
plugin A is using a local copy of the interface assembly and the client is
using its own copy of the interface assembly. Even if both define the exact
same type the CLR will treat them as two completely different types because
they are housed in different assemblies.

For simplicity I would put the interface assembly in the same directory as
the client (the directory where appdomain's appbase is pointed at) and not
put any other copies where the plugins will try to load them.
 
Sorry, I think I've confused you.

I was hoping that my plugin interface source file could be shared across my
plugin manager ( framework ) assembly and my plugin assemblies - rather than
having to have an intermediate plugin interface assembly.

Now because I want the plugin manager to get an instance of the plugin
object that I get through the plugin interface I also need to define this in
my intemediate plugin interface assembly. It feels a bit messy, but not sure
if I can get around it as I understand your comment that the CLR will treat
classes different if they were created in different assemblies even if they
are from the same shared source file - hence I cannot cast between the share
source file class compiled in assembly 1 to the same share source file class
compiled in assembly 2.

Maybe I need to look at this again, as it feels a bit messy - try and reduce
a bit of the clutter.

Rich.

David Levine said:
You can define the interface in a single assembly but you need to manage how
many copies of it are floating around. What's probably happening is that
plugin A is using a local copy of the interface assembly and the client is
using its own copy of the interface assembly. Even if both define the exact
same type the CLR will treat them as two completely different types because
they are housed in different assemblies.

For simplicity I would put the interface assembly in the same directory as
the client (the directory where appdomain's appbase is pointed at) and not
put any other copies where the plugins will try to load them.



RichS said:
Hi,

[ BTW I'm using C# ]

I'm trying to implement a Plugin architecture where I have a single UI
framework, and then load dll components into that framework.

At the moment I'm constructing the Plugin loading mechanism, I've created
a
plugin interface ( that the plugin clients must implement ) and a
pluginhost
interface ( thart the ui framework plugin manager must imlpement ).

When the UI framework loads the plugin assembly it checks the types in the
assembly to ensure it supports the plugin interface, if it does then it
constructs an instance of this type and casts it to the plugin interface
type.

If I create a source file with these interfaces in and link this file (
i.e.
share the file )into each project then I get a CastException - in
CreatePluginInstance - when I cast to the plugin interface type. If I
implement this interface in a separate dll and then reference this in the
framework and the pluginclient, then the cast succeeds.

I suppose this works, but I would rather keep the number of dlls to a
minimum, and hoped to be able to get away with just sharing the interface
source file. Is this possible ??, or do I need to implement it this way
??

regards
Rich.


CODE:

Interface.....

namespace PluginInterface
{
public interface IPlugin
{
IPluginHost Host{ get;set; }
}

public interface IPluginHost
{
bool Register(IPlugin ipi);
}
}


PluginCreation and Cast...

Assembly objAssembly = Assembly.LoadFrom(_strPath);

foreach (Type iterTypes in objAssembly.GetTypes())
{
foreach (Type iterInterfaces in
objIterGetAssemblyTypes.GetInterfaces())
{
if
(iterInterfaces.Equals(typeof(PluginInterface.IPlugin)))
{
CreatePluginInstance(iterInterfaces);
}
}
}
}

public void CreatePluginInstance( Type _assemblyType )
{
PluginInterface.IPlugin sui_Plugin =
(PluginInterface.IPlugin)Activator.CreateInstance(_assemblyType);
}
 
RichS said:
Sorry, I think I've confused you.

I was hoping that my plugin interface source file could be shared across
my
plugin manager ( framework ) assembly and my plugin assemblies - rather
than
having to have an intermediate plugin interface assembly.

When you share a source file across multiple assemblies, .NET regards the
types as being different. This is because a types classification is partly
made up by the assembly. Therefore, if class MyClass (in MyClass.cs) is
included into assembly A and assembly B, then .NET sees "MyClass, A" and
"MyClass, B" as the type names (I've simplified this a bit), and therefore
concludes that they are different types.
Now because I want the plugin manager to get an instance of the plugin
object that I get through the plugin interface I also need to define this
in
my intemediate plugin interface assembly. It feels a bit messy, but not
sure
if I can get around it as I understand your comment that the CLR will
treat
classes different if they were created in different assemblies even if
they
are from the same shared source file - hence I cannot cast between the
share
source file class compiled in assembly 1 to the same share source file
class
compiled in assembly 2.

You could have one "master" assembly that contains your shared type
interfaces as well as you default implementation of the host interfaces.
Then, the client assembly would reference this master assembly in order to
implement it's types. In addition, anyone wanting to provide their own host
interfaces could also reference this assembly, and pick and choose which of
your implementation classes (if any) to use. This would cut things down from
3 assemblies to 2. Following the same scenario, your default client class
implementations could also be included into the master assembly. Then, for
the default system, only one assembly would be required.
Maybe I need to look at this again, as it feels a bit messy - try and
reduce
a bit of the clutter.
[snipped]
 
Excellent, thanks.

Sean Hederman said:
RichS said:
Sorry, I think I've confused you.

I was hoping that my plugin interface source file could be shared across
my
plugin manager ( framework ) assembly and my plugin assemblies - rather
than
having to have an intermediate plugin interface assembly.

When you share a source file across multiple assemblies, .NET regards the
types as being different. This is because a types classification is partly
made up by the assembly. Therefore, if class MyClass (in MyClass.cs) is
included into assembly A and assembly B, then .NET sees "MyClass, A" and
"MyClass, B" as the type names (I've simplified this a bit), and therefore
concludes that they are different types.
Now because I want the plugin manager to get an instance of the plugin
object that I get through the plugin interface I also need to define this
in
my intemediate plugin interface assembly. It feels a bit messy, but not
sure
if I can get around it as I understand your comment that the CLR will
treat
classes different if they were created in different assemblies even if
they
are from the same shared source file - hence I cannot cast between the
share
source file class compiled in assembly 1 to the same share source file
class
compiled in assembly 2.

You could have one "master" assembly that contains your shared type
interfaces as well as you default implementation of the host interfaces.
Then, the client assembly would reference this master assembly in order to
implement it's types. In addition, anyone wanting to provide their own host
interfaces could also reference this assembly, and pick and choose which of
your implementation classes (if any) to use. This would cut things down from
3 assemblies to 2. Following the same scenario, your default client class
implementations could also be included into the master assembly. Then, for
the default system, only one assembly would be required.
Maybe I need to look at this again, as it feels a bit messy - try and
reduce
a bit of the clutter.
[snipped]
 
Excellent, thanks.

Sean Hederman said:
RichS said:
Sorry, I think I've confused you.

I was hoping that my plugin interface source file could be shared across
my
plugin manager ( framework ) assembly and my plugin assemblies - rather
than
having to have an intermediate plugin interface assembly.

When you share a source file across multiple assemblies, .NET regards the
types as being different. This is because a types classification is partly
made up by the assembly. Therefore, if class MyClass (in MyClass.cs) is
included into assembly A and assembly B, then .NET sees "MyClass, A" and
"MyClass, B" as the type names (I've simplified this a bit), and therefore
concludes that they are different types.
Now because I want the plugin manager to get an instance of the plugin
object that I get through the plugin interface I also need to define this
in
my intemediate plugin interface assembly. It feels a bit messy, but not
sure
if I can get around it as I understand your comment that the CLR will
treat
classes different if they were created in different assemblies even if
they
are from the same shared source file - hence I cannot cast between the
share
source file class compiled in assembly 1 to the same share source file
class
compiled in assembly 2.

You could have one "master" assembly that contains your shared type
interfaces as well as you default implementation of the host interfaces.
Then, the client assembly would reference this master assembly in order to
implement it's types. In addition, anyone wanting to provide their own host
interfaces could also reference this assembly, and pick and choose which of
your implementation classes (if any) to use. This would cut things down from
3 assemblies to 2. Following the same scenario, your default client class
implementations could also be included into the master assembly. Then, for
the default system, only one assembly would be required.
Maybe I need to look at this again, as it feels a bit messy - try and
reduce
a bit of the clutter.
[snipped]
 
Back
Top