Shared members between interfaces

I'm new to MEF but have my basic plugin manager working (sort of) in my app.

I'm trying to structure such that small pieces of functionality are included in seperate interfaces and then the plugin implements one or mor of these interfaces depending on what they need to support.

Also overtime I can then introduce more interfaces for new plugin points in my host app without breaking existing plugins.

That's the plan anyway.

However stuck on one thing.

In my host app I load all plugins supporting the particular interface into a list of the Interface type. So

PluginslistA = all plugins in dir supporting InterfaceA

PluginslistB= all plugins in dir supporting InterfaceB

So now I can loop around each of these lists at my host plugin points to call functionality from the Plugin. That all works fine.

OK So from my Plugin Side I have:

Class Plugin

Property ABC

end Property

Inplements InterfaceA

Implements InterfaceB

Sub xxxx implements InterfaceA.Sub1

Sub yyyy implements InterfaceB.Sub2

end class

So to my question. I'd liek to be able to have some common properties/variables in my plugin that are shared between both Intefaces; what I mean by this is if i loop around all PluginslistA or PluginslistB I's like to be able to reference
some common data.

So if i'm calling Sub yyyy from my PluginslistB and I set property ABC then I want Property ABC same data to be visible when I loop around PluginslistA (ie from Sub xxxx); howver at the moment they seem to be different instances of the data.

I tried to create at the Interface level and have a "core" interface where I add the properties and then let the other Interfaces inheret ie

Interface Core

Prop ABC

InterfaceA

Inherits Core

Subxxxx

InterfaceB

Inherits Core

Sub yyyy

This exposes the same properties of the core interface but the data instances are different.

Class Plugin

Property ABC implements InterfaceCore.ABC

<i want this same data value to be accesible from InterfaceA and InterfaceB>

end Property

Inplements InterfaceA

Implements InterfaceB

Sub xxxx implements InterfaceA.Sub1

Sub yyyy implements InterfaceB.Sub2

end class

I can loop around all PluginslistA or PluginslistB individually from the host app and set prop ABC to a value but there must be an easier way to share data.

Can any guru out there advise how i can accomplish common data in a plugin that can be accessible from subs impleting different interfaces?

So I need a shared member class or something and if so an example merged in with above gratefully received so i can see how I should fit together

SharedClass , which has shared data that is shared between the above two classes.

I have a condensed version of what I think your scenario is. In the below code you can throw all your shared data into SharedData, which will be shared amongst all the instance of IFoo and IBar that are created.

Hopefully this should get you what you need . Please let me know if I have completely misunderstood your scenario .
J

I'm new to MEF but have my basic plugin manager working (sort of) in my app.

I'm trying to structure such that small pieces of functionality are included in seperate interfaces and then the plugin implements one or mor of these interfaces depending on what they need to support.

Also overtime I can then introduce more interfaces for new plugin points in my host app without breaking existing plugins.

That's the plan anyway.

However stuck on one thing.

In my host app I load all plugins supporting the particular interface into a list of the Interface type. So

PluginslistA = all plugins in dir supporting InterfaceA

PluginslistB= all plugins in dir supporting InterfaceB

So now I can loop around each of these lists at my host plugin points to call functionality from the Plugin. That all works fine.

OK So from my Plugin Side I have:

Class Plugin

Property ABC

end Property

Inplements InterfaceA

Implements InterfaceB

Sub xxxx implements InterfaceA.Sub1

Sub yyyy implements InterfaceB.Sub2

end class

So to my question. I'd liek to be able to have some common properties/variables in my plugin that are shared between both Intefaces; what I mean by this is if i loop around all PluginslistA or PluginslistB I's
like to be able to reference some common data.

So if i'm calling Sub yyyy from my PluginslistB and I set property ABC then I want Property ABC same data to be visible when I loop around PluginslistA (ie from Sub xxxx); howver at the moment they seem to be different
instances of the data.

I tried to create at the Interface level and have a "core" interface where I add the properties and then let the other Interfaces inheret ie

Interface Core

Prop ABC

InterfaceA

Inherits Core

Subxxxx

InterfaceB

Inherits Core

Sub yyyy

This exposes the same properties of the core interface but the data instances are different.

Class Plugin

Property ABC implements InterfaceCore.ABC

end Property

Inplements InterfaceA

Implements InterfaceB

Sub xxxx implements InterfaceA.Sub1

Sub yyyy implements InterfaceB.Sub2

end class

I can loop around all PluginslistA or PluginslistB individually from the host app and set prop ABC to a value but there must be an easier way to share data.

Can any guru out there advise how i can accomplish common data in a plugin that can be accessible from subs impleting different interfaces?

So I need a shared member class or something and if so an example merged in with above gratefully received so i can see how I should fit together

In case you need to update the SharedState, you should have some method/ property exposed in your FooA an BarA classes that lets you change the "shared" SharedState variable. This update would then be visible to all the other users of that SharedState instance.
I hope that this helps.. let me know if that does not answer your question .

//In case you need to do this updating in another method, you can store data in a private field of the class and do the whatever you need to there.

shared data class would need to be in the same catalog as all the other classes. Where you put it in terms of the proeject should not make a difference to MEF as long as all the types that are required to do a composition are present in the
catalog.

You've been great coming back to me but try as I might I cant get this to work. Yep it sets the value in the New() constructor in VB but then whenever I update the variable in the methods then the values dont get updated. I guess my knowledge
here is now advanced enough to string snippets together into something theat works. My brain is fried on this!

Public Class PluginRepository <ImportMany("IClientPluginCore")> _ Public Property ClientPluginCore() As IEnumerable(Of IClientPluginCore) Get Return _ClientPluginCore End Get Set(value As IEnumerable(Of IClientPluginCore)) _ClientPluginCore = value End Set End Property Private _ClientPluginCore As IEnumerable(Of IClientPluginCore) <ImportMany("IClientPluginMain")> _ Public Property ClientPluginMain() As IEnumerable(Of IClientPluginMain) Get Return _ClientPluginMain End Get Set(value As IEnumerable(Of IClientPluginMain)) _ClientPluginMain = value End Set End Property Private _ClientPluginMain As IEnumerable(Of IClientPluginMain) <ImportMany("IClientPluginMenus")> _ Public Property ClientPluginMenus() As IEnumerable(Of IClientPluginMenus) Get Return _ClientPluginMenus End Get Set(value As IEnumerable(Of IClientPluginMenus)) _ClientPluginMenus = value End Set End Property Private _ClientPluginMenus As IEnumerable(Of IClientPluginMenus) <ImportMany("IClientPluginStatusMenus")> _ Public Property ClientPluginStatusMenus() As IEnumerable(Of IClientPluginStatusMenus) Get Return _ClientPluginStatusMenus End Get Set(value As IEnumerable(Of IClientPluginStatusMenus)) _ClientPluginStatusMenus = value End Set End Property Private _ClientPluginStatusMenus As IEnumerable(Of IClientPluginStatusMenus)End Class

Then at any points in my main app where I support a particular plus point I'd do on/both of:

For Each ClientPluginMain In PluginRepository.ClientPluginMain
....call a sub or set a property
next
For Each ClientPluginMenus In PluginRepository.ClientPluginMenus
....call a sub or set a property
next

All of this works OK so far but even with your pointers I cant see how to share data. In the snippet below for example

It seems to me that if I have a plugin that supports both of the above interfaces then the above 2 lines create two parallel instances of teh pllugin that then cant talk to eachother. It's like the run in a parallel
isolated universe.

So if I then put myself in a plugin contributor, they write something like..

Public ReadOnly Property Name() As String Implements IClientPluginMain.Name Get Return _Name End Get End Property Private _Name As String

Public ReadOnly Property UniqueID() As String Implements IClientPluginMain.UniqueID Get Return _UniqueID End Get End Property Private _UniqueID As String

Public ReadOnly Property Image() As Image Implements IClientPluginMain.Image Get Return _Image End Get End Property Private _Image As Image

Public Property Host() As IClientPluginHost Implements IClientPluginMain.Host Set(value As IClientPluginHost) _Host = value End Set Get Return _Host End Get End Property Private _Host As IClientPluginHost#End Region

Now because they've declared a common variable in thier code then the would expect to be able to access it from any subroutine but in fact because of my "parallel universe" scenario as the plugins get loaded the data isnt what
you expect. I think then that might confuse plugin contributors.

The only way it seems to me that you can set the variable is dyuring instantiation (new()sub) or by looping around all objects in the Reporsitory and trying to sync them by some method.

I coded this way based on examples and discussions on the Net because I want to be able to introduce new functionality in my API over time without breaking existing plugins. Also not all plugins then need to implement the
same Interfaces. That's my (maybe misguided) logic here.

I know I'm doing something wrong here and welcome any help or will even buy a book to try and understand further but I feel I'm missing something and need to sort out before I go much further. What I've done so far works
OK but am I on the right path.

However, even in this snippet there are problems. The container shouldn't be used to 'retrieve' things on demand like this most of the time - the dependencies on the two sets of plugins should be an import on yet another part.

This is a pretty tricky topic. The MEF examples in it are fast becoming outdated, however for the general concepts I'd strongly recommend Mark Seemann's book "Dependency Injection in .NET" -
http://manning.com/seemann

Your suggestion about the container seems to have moved me on a great deal. I think (needs more testing) variables can see eachother now.

Could you expand a tad on "The container shouldn't be used to 'retrieve' things on demand like this most of the time - the dependencies on the two sets of plugins should be an import on yet another part."

You're right though in that it seems to be fast moving; let's hope it doesnt totally pass me by..! :0)

Now, the point isn’t to cut down on calls to the container, and you would not then go and access “A” and “B” properties on “C” – rather, C should be a meaningful class that encapsulates A and B to do some kind
of work. Following the above statement you’d usually see something like:

c.DoWork();

The primary reason for designing your application this way is to make the dependency structure of your application explicit – things declare what they need as imports, rather than helping themselves via the container.

Hopefully this will help you clarify some of the other materials on the subject, best of luck with it!

Your suggestion about the container seems to have moved me on a great deal. I think (needs more testing) variables can see eachother now.

Could you expand a tad on
"The container shouldn't be used to 'retrieve' things on demand like this most of the time - the dependencies on the two sets of plugins should be an import on yet another part."

You're right though in that it seems to be fast moving; let's hope it doesnt totally pass me by..! :0)

Thanks for this. I'm not sure I fully understand as my C isnt too good either. I ran though a converter to piece together but code is to sparse for my simple mind to place into context fully around what I already have. I tried
but it didnt do anything.