Ways to add functionality to a C# app without recompiling - c#

What ways have people found/used to add functionality to a .NET/C# app without recompiling?
The methodology that comes to mind for me is having code that looks for a file to read, parses that file, and then dynamically creates controls and their event handlers, etc., based on what is contained in the file (possibly an xml file).
Or would dynamically loading .DLLs be considered "not recompiling"?
Any ideas/"war stories"?

All you need - MEF - Managed Extensibility Framework

For fairly simple cases with well defined behaviors:
Define an interface for you plugin.
Implement the interface in dlls.
Load dlls with Assembly.LoadFrom.
I'd add a GUID to each dll too so you can tell them apart.

Look at how ASP.Net does it - you can add ASPX/ASPX.cs file while site is running. Short version: ASP.Net listens for file changes and compiles new files into new assemblies, than loads into existing AppDomain to use for rendering new pages.

Related

How can i load just specific Plugins by MEF?

For my company, I'm developing a simple GUI Framework which can be universally used. I want the GUI Framework to read a config file when starting up, which defines, which Plugins should be loaded, where their GUI elements should be arranged, and so on. But the reading of the config file, and also some writing, should happen through a plugin. So that's why, this plugin should be loaded first, because before others can be loaded, it needs to read out the config file to identify them.
I found out, that I can load just a defined dll like this:
var dirCatalog = new DirectoryCatalog(#"..\..\Extensions\","ProgramConfigManager*");
But I don't want to rely on the filename. My intention is to first load the MEF plugin with the Interface ISAProgramConfigManagerContent:
[Import(typeof(ISAProgramConfigManagerContent))]
SAProgramConfigManagerContent PCM;
After this, the other Plugins, but just the ones in the config file should be loaded into this:
[ImportMany(typeof(IPlugin))]
List<IPlugin> Plugins;
Is there a way, to first just load the special Plugin which handles the config file, by filtering the contracts and just compose the one of type ISAProgramConfigManagerContent ?
Thanks in advance.
When importing from other assemblies, you must tell MEF which in files to have a look. This is either a directory, by file globbing, or any other custom means. Otherwise MEF has no way where to look for the export.
Having said this, you could first setup a catalog to load the plugin manager. And then, based on that, setup another catalog with the entries that you want to load and import the plugins programmatically from that. You can also use an AggregateCatalog to unite several DirectoryCatalogs.
Something like:
var container = new CompositionContainer(aggregateCatalog);
IEnumerable<IPlugin> plugins = container.GetExports<IPlugin>();

How to hide DLL functionalities?

Consider the following situation:
I have developed a DLL file DCore. Afterwards I developed a DLL file DCustomer which uses methods from DCore. Now I want to distribute DCustomer as DLL for a customer and make sure to hide all functionalities of DCore, so that the customer can only access the functionalities of DCustomer.
How can I hide the functionalities of DCore when creating the DLL file DCustomer?
There is nothing much you can do about it.
But do check out StrongNameIdentityPermissionAttribute
I would also request you to check out this Thread

Code reuse in non-compiled project

I have a non-compiled web app which has several pages that all have similar functionality. If I compile the code it's easy to share classes between files, but I'm having trouble achieving the same without compiling. If I have an XmlRequest.cs file, how do I access its class from Compare.aspx.cs?
If you add XmlRequest.cs to a folder named App_Code, it will be available throughout your webapp.

Add custom version information to C# application

Application is a C# .Net 3.5 WCF Service.
I'd like during the build process to dynamically add some build information to the final binary and assemblies that can then be read programatically and sent back to the WCF client when it sends a GetVersionInfo request to the web service.
.Net assembly versioning isn't enough. I want to include additional string data that contains the state of the system at the time the application was built.
I'm thinking that I'd do this by adding a post build event to call a script to update the app.config file with the data I want. Does this sound about right, or should I be considering some other approach?
Update
I'd additionally like this string to appear in the "Special Build Description" property of the final exe. I.e. I'd like to right click on the file and see this information in the version tab for the file.
Thanks in advance.
I suspect a pre-build event may be more appropriate than post-build... have you considered adding a buildinfo.xml file (or similar) to be built into the assembly as an embedded resource? You could then load it with Assembly.GetManifestResourceStream. That way you don't need to worry about fitting in with existing files or anything like that - just overwrite buildinfo.xml with a new file in the pre-build step.
You have to decide how important it is that the information you want to exchange is tied to the executable file itself.
Updating the config file during the built is a workable model, but it places the information in a location where it could be altered by anyone with access and a text editor.
Updating information after a build in a compiled assembly is certainly possible, but it's fragile and breaks down if you ever decide to sign the assemblies. It's also a lot of work, since there's no built it support for re-writing assembly files in this manner.
An alternative you should consider, is creating your own custom assembly-level metadata attributes and assigning them during the build process. You could even place them in a separate code file (or append them to AssemblyInfo.cs) as part of you build.
You could also consider creating an embedded resource (an XML file, for instance), and retrieving it from the assembly manifest at runtime.
Either of the above approaches would require you to use a pre-build custom step rather than a post-build step.
Personally, I find the metadata attributes a convenient approach if there isn't a lot of data. Otherwise, I would consider using an embedded resource file.

Extending ExplorerBrowser from the Windows API Code Pack to display non filesytem files

I'm writing a WPF program in C# that needs to render a set of files in a file browser to the end user. The ExplorerBrowser control found inside the Microsoft Windows API CodePack contains much of the functionality I need... e.g. thumbnails of different sizes, sorting, browsing, etc...
The catch is that the files are not coming from the disk, but are available over a custom network transfer protocol.
I was originally thinking that I could simply extend the ShellObjectContainer class and ShellObject classes to provide the features I require, by essentially building an Adapter. However I've run into difficulties because these classes use internal constructors.
Overall it's looking like this API is rather hostile to extension, is there anyway to extend these components to do what I need, or am I better rebuilding much of ExplorerBrowsers functionality by creating a custom WPF component, perhaps by extending ListBox?
Yes, this certainly wasn't made to be extensible. Hard to see how you could get anywhere at all unless you create your own shell namespace extension. So that it is viewable in a shell window. Doing so is quite brutal in managed code, the shell's COM interfaces derived from IUnknown are very hard to use. Which is what the wrapper classes in the API code pack is doing to get a browser window in a managed program.
Creating the shell namespace extension is the greater solution, your custom files would be visible in a regular Explorer window as well. But write that kind of code in C++, both because it is so much easier to get the COM code going and to avoid injecting the CLR in any program that uses a File + Open dialog box. Although that is now technically supported by .NET 4.0

Categories

Resources