# Visual Basic > Visual Basic .NET >  Copy Local without having a reference - MEF

## FunkyDexter

Hi Guys.

I have a solution that uses MEF plug ins.  It consists of 3 projects.
1. The "engine" project.  This does the actual work and consumes plugins to do so.  It contains an interface that defines the contract a plugin should adhere to.
2. The plugin project where individual plug ins are implemented.  This contain a reference to the engine project because it needs to access the plugin interface.
3. A UI project.  This contains a reference to the engine project so it can call it's methods.  It also contains some calls to the methods on the plugin interface but never addresses a concrete instance of a plugin.  This is the start up project for the solution.

In design architecture terms this is all good and is giving me a nice separation of concerns.  But, at present, the UI project also has a reference to the plug ins project which it shouldn't need as it never addresses anything concrete in that project.  The only purpose the reference is serving is to force the plugins project to be built and copied locally to the bin debug folder for the UI project.  I would like to separate this operation from the reference if possible - mostly because it'll force me to be disciplined and not address anything in the plug in project directly.

I have removed the reference and replaced it with a project dependency which successfully gets the plug in to build but does not result in it being copied to the UI projects bin debug folder, meaning that none of the plug ins are available at run time when debugging.  Is there a way to do this?

I figure I can add a copy as post build action of the plug in project but this feels a bit flakey.  The engine (and therefore the plugins) is designed to be consumable by multiple different UI's which would mean adding new copy actions as new UIs are implemented.  It's also likely that other devs may work on this in the future and I can't guarantee that they will structure their repos in the same way as me so the relative paths may change.

What I'm really looking for is the ability to set CopyLocal on a dependency rather than a reference.  Can anyone suggest a way of doing this?  I was kinda expecting visual studio to support it somehow but I can't find an option for it.

----------


## Shaggy Hiker

I am working on something like this, but I didn't even TRY to take it to the level that you did. I don't expect my plugins to be part of the project. They just have to be in a certain system folder, which is similar to how mods work for games. The main project has a reference to the project that maintains the interface definitions, but doesn't have anything about the plugins in the bin folder, or any direct knowledge of them whatsoever. When the project starts up, it goes to the folder where plugins are located and uses refection to see what objects are in there (or actually, which interfaces the objects implements, as it doesn't understand the actual objects, just the interfaces).

This imposes more work on my part, because I'm manually copying the dll from the plugin project into the plugin folder. When it was just three or four plugins, that wasn't really a burden. Once it got higher (it's up around 30, currently), I wrote a whole other project to copy either the release or debug from ALL the plugin projects into the plugin folder, along with some tools to manage the set of plugins to copy.

Having VS do that automatically would be really nice. Heck, having VS automatically build both debug and release versions on every build would be nice, since I have all the copying down to a single button click.

----------


## FunkyDexter

Yeah, I could do that and have done it before but it can make debugging a pain as you can't step into a plugin (although you probably could if the pdb file was present, not sure).  It also means I have to right the MEF catalog to access a set folder which can be a bit weird when our installer for the main product allows the user to select an install folder.

Putting the plugin project in the main solution means that everything get's build and, if you've got a reference, copied to the output folder.  So you can just have the MEF catalog address the AppDomain folder to pick up anything in the Bin Debug when running from Visual Studio and anything in the install folder in production.  I personally add catalogs for all sub folders because it means clients can drop their own plug in implementations into sub folders if they like - they tend to like to name these to help keep things organised.

The problem is that I want to get rid of that pesky reference.  It's only in there to control the _build_ behaviour which isn't really what references are meant to be for.  They're meant to create a functional dependency which is exactly what you _don't_ want with a plugin architecture.

----------


## Shaggy Hiker

There is no issue with stepping into a plugin. I've never understood how VS does that, but it does. I've confirmed this every way I can think of, too, so I'd be pretty surprised if I was mistaken about this.

When I create a new plugin for this project, it's a totally separate project. It has no ties to the main project, except that they both reference the common dll that holds interface definitions. I take the build output of the plugin, copy it into some folder that is not associated with the project in any way, not via some VS setting, nor by any other means that I can think of.

All plugins of type X have a OnDrop method in the interface they implement. If I put a breakpoint in the main project at the call to the OnDrop method, I step into the code in the plugin, and can see all of that code in the debugger. Not just the public code, but private, and comments, which means I'm seeing the source file from the plugin project. 

If I then open the plugin project, make a change to the source and rebuild, but neglect to copy the newly built output over to the folder that the main project uses, then when I try to step into the OnDrop method, VS tells me that the code being used is not the same as the source file and refuses to show it.

Therefore, by means that I don't quite understand, VS is able to take that dll that I opened, find the source code located in some other folder on the computer, and correctly show me that source code, so long as the source and the destination are the same.

That last part I understand. The assemblage has a signature. If the signature of the dll that is being loaded by the main project matches the signature of the dll in the bin folder of the plugin project, then it shows the source code. The signature must be telling it whether to look at release or debug. Either one works, but stepping through the source in the case of a release build is unreliable. Optimized code doesn't necessarily correspond one to one with the source, so an optimized release build will cause the debugger to appear to 'skip' lines in the source. That doesn't happen with the debugger.

Presumable, VS knows something about where project folders are located and can use that to try to find a dll that matches the dll that was loaded, and thence to the source, but what limits there are on this process I don't know. I have never tried moving the plugin project to strange places on the hard drive to see whether VS can find it. Probably not. Still, no pdb file is required for this to work, and up until either VS2022 or VS2019, there was no difference between the release or debug builds and stepping through the source of a plugin. That still doesn't make sense to me, as optimization SHOULD make it impossible to step through source code when you are using a release build. The current situation makes more sense than that, but I got into the habit of only making release builds of plugins because it just didn't matter. I did that for several years, and have only switched to not using the release builds of plugins in the last year or two.

In my setup, the main program can go wherever the user wants, but the plugins have to go in a known location based off a system directory. That's a pretty standard approach with games that use plugins. It needs to know where to look for the plugins, but the plugins don't need to know where the main program is, since they don't hold a reference to them. They don't need to know where the common interface is, either, since the main program has loaded that. It's there, if the plugin needs it.

----------


## FunkyDexter

> the plugins have to go in a known location based off a system directory


That's a possible thought.  What do you typically use?  I guess I could use App_Data.

----------


## Shaggy Hiker

I forget, and I'm on the wrong computer to look, but that does sound about right.

----------

