I as of yet, have not had a need to create a dll in .NET as my programs tend to be distinct from one another (and I haven't programmed for too long). However I am starting to gather a library of regularly used methods now which tend to have copies in lots of my programs (or similar methods that could be made more generic).
As I understand it a dll should be created to share common methods between programs.
So I can put my methods in the dll, what about things like custom dialog boxes and common forms. I currently have a custom error form and a print preview dialog which are used in almost all my programs. Is it good practice to put these in a dll?
"Good practice" in this case really relies on how much code-duplication you're cutting down on. If these dialogues are used throughout a lot of your programs and they take up a lot of code, then yes, it's probably a good idea to move them to a shared space.
But don't be tempted to throw everything in there. You'll find yourself having to override it and by that point you're probably writing more code than you were before. Keep things simple. Keep them generic. Keep them useful.
Before you start, though, be aware that you are creating a dependency tree. If you update your library chances are you'll have to put in some time maintaining your apps that use it... But this is no different from using a third-party lib.
To create a new dll, you just add new project (library) to your solution, and add it as a project reference to your main programme.
It is possible to put anything you want to this project. All dialog boxes, user controls, etc. are just classes, so you can share them as easily as any other class. I think it is good practise to share as much as possible.
Sure why not?
What you're building here is actually a small framework, pretty much like the .Net framework itself. Everything that you think is common between your applications can be put in the assemblies: forms, methods, business logic, exceptions, common data access.
When your framework grows you might want to split up that common DLL. For example if you have common forms in a DLL and you also develop batch applications then they don't need to reference to the DLL containing the WinForms specific classes.
Alternatively you can put the source files for these methods in a common place and just add them as links when you include them in your project/solution.
Related
Currently I'm working on a .NET hobby project that involves a complex system of objects which work in combination with eachother. However, I encountered a little problem, I am unable to find a mechanism in .NET to support replacing code at runtime, and be able to dispose of the old code, loaded previously. This means replacing a module/object dynamically and almost instantly displaying the changes to the user, for example, when he restarts a procedure, but not the whole program.
I have already taken into account the possibility of having separate AppDomain for each session and loading the necessary assemblies into it but this seems a little bit too expensive. I should also mention that every session benefits from a common base of assemblies, for instance, to connect to a database, so this means loading those classes into every single session. Marshalling data back and forth from the separate AppDomain also represents an additional overhead (could be used when data is sent to the client application through the network, code for this contained in the main AppDomain, which manages the sessions).
Is there a framework or way of replacing/unloading particular parts of code? How is it done in real-world applications? Can there be a workaround? Or have I picked the wrong set of tools?
You need some kind of plugin system with well defined interfaces. Then you load at runtime binaries (your plugin *.dll) and create objects from it and then execute methods on it.
When you create a system where objects from your plugins must be created through your IPluginManager you have no problem with replacing code at runtime. :)
Or
You have something like a folder with *.cs files which will on demand compiled (in memory) and create the objects you want to use from them and call the methods on them.
Which is basically the same like above, without compiling at run time.
From there you can make further improvements.
EDIT:
Like you wrote the only problem without using AppDomain is that once loaded assemblies can't be unloaded. But that's not really a problem.
I don't think you need separate AppDomains: you can dynamically load assemblies within the current AppDomain. And each assembly should probably implement some defined interfaces (depending on your usage). You could use the FileSystemWatcher class, for example, to load/unload assemblies as needed.
See http://msdn.microsoft.com/en-us/library/25y1ya39(v=vs.110).aspx
You can have a look at MEF. It stands for: Managed Extensibility Framework .
Here's another article about it MEF on codeproject.
It is used to load dll's in runtime by composing them. This is what is usually used for plugins or anything else you kinda drop into a folder and expect it to run .
Here's a link to some more tutorials as well: Where can I learn about MEF?
Yes, you're right, it is not possible to simply unload an assembly (only AppDomains). But I think one of the features of ASP.Net vNext is the ability to have just in-memory assemblies and when you simply alter the source code on the drive it gets automatically compiled and loaded. Therefor a mechanism must exist to unload the previous version.
I think they are doing that by simply creating a AppDomain where all assemblies are loaded into again to avoid any cross domain communication. But i don't really know and maybe if you would dig more into the mechanism on how they do this stuff in ASP.NET you maybe find a good solution. More informations about the hot topics from vNext you can maybe also find at Scotts Blog.
Well, I've found 2 solutions that work for me, which I would like to share. The first one is to use CollectibleAssembly and define the types. This is certainly a bit tricky, and a number of restrictions are imposed on this type of dynamic assembies.
The other option is to use a scripting language like IronPython or IronRuby. Also a great feature of the new Roslyn compiler is that it also provides scripting APIs, not previously available in the .NET framework. What's more, the Roslyn scripting languages tend to look very much like their full-blown equivalents (C# or VB). And I've also found a tiny example of its capabilites.
Hello everyone
Currently I have the following reference structure:
DSFinalProject have reference of "DAL" project and "DataStructure" project.
DataStructure have reference of the DAL project as well…
Now I want that DSFinalProject won't have reference to the DAL layer but will be able to use interfaces from that class.
Is there any way to "tunnel" the interfaces that are in the DAL project to DSFinalProject without actually making references between them?
Maybe using the DataStructure project? Or anything else?
Thanks in advance for any help :)
The easiest way is to put them in DataStructure, which isn't too bad since anything that references the interfaces will need to reference DataStructure as well.
My vote would be to put them there until you run into a scenario when you need to have the interfaces in a separate assembly.
I don't know of any way to reference interfaces (or anything else) inside the DAL project from DSFinalProject without having a reference to the project (or assembly).
You can move them to another project if you think it makes the dependencies cleaner - if you put the interfaces in the DataStructure project - you'd run into a circular reference where it needs DAL and DAL needs it.
I don't believe that there is anyway to so what you ask. If you think about what happens when you serialise objects, you still need the assembly to provide the low level structure of how the fields are laid out inside the stream of data. It needs the code in the interface to say that the first 4 bytes are a double, etc.
So the only to do this is to move your interfaces into a new interfaces.dll which can be referenced by everything. You will see this pattern repeated in many examples including the EnterpriseLibrary.
However...
you are making a classic mistake. Why are you splitting your code into so many projects? Projects really should be thought of as the run time packaging of our code, not a desing time segregation mechanism. By splitting into so many assemblies, you do three things.
You slow your build system down, as the compiler does more work fetching the other assemblies.
You slow down Visual Studio as it works harder to load up all the projects and keep the references between them. I once worked on a solution with 140 projects that took 15 minutes just to open (but I always got my morning coffee).
You slow down the run time performance as DotNet has to search around for another 4k dll (thats the minimum, even for just one line of code). Try looking at the fusion logs or use SysMon to see just how much work is involved in this simple operation.
Take a look at this example Hints on how to optimise code do see what's going to happen as your solutions get more complicated.
Instead of splitting it like this, use namespaces instead, you will still have the seperation, but instead of having to use so many references, you now have control by the using statements inside your classes. You will easily see if you are using a DAL reference in a class designed to be in a DSFinalProject tier. You can just create a folder under the project and add your classes there instead. Get rid of all the projects and still have a properly tiered system.
As your solution grows, wait until you have at least two executables before you start introducing projects, and then consider the run time implications. If you are always going to load up two assemblies, merge them into one (I've seen some open source projects these days that use ilmerge to merge in third party libraries too).
I've an application which is basically a designer with preloaded controls where you can design your pages using the controls.
I'm planning to release more and more controls in the future. I don't want to release a new build for newly added controls as it has its disadvantages. So I was thinking of addon/plugin kind of architecture where I just release the addon/plugin separately which they can install and get the controls inside the designer.
Right now I'm using xml files as addons to specify the controls, its behaviors, its styles etc. Each xml (addon) represents a single control. But I'm finding it very difficult to implement this since I've to write a generic parser to read all the plugins.
Instead, can I release a dll for each addon which gives me more control to write code to define the behavior/look of the control and dynamically load it through the main engine? If so how can I check for dlls and load it dynamically in my application?
You might want to look at the Managed Extensibility Framework. This will probably solve most of your issues and more, but will require learning some new tech...
You should also definitely look into the System.Addin Namespace as mathieu suggests!
If you want to go with your own route, I suggest the following approach:
an interface for addons in your main application
implement that interface in addon dlls
load the dlls at runtime with Assembly.Load
you might want to look into loading the addon assemblies into a separate AppDomain
You should have a look at System.Addin namespace, as it really fits your need. After an addin is developped, you just have to drop it in a folder, and it is available (at runtime) for your application.
http://kentb.blogspot.com/2008/06/maf-gymnastics-skeletal-solution.html
See this question for comparison : Choosing between MEF and MAF (System.AddIn)
The MEF or System.Addins routes mentioned are likely the most efficient way to go about this. I only pipe in to say a few things about the alternatives.
I have "hand rolled" this sort of solution a number of times and I would say that unless there is a compelling reason to do it from scratch it is better to use an existing addin framework. But if you are going to do so, I have found dependency injection containers like Castle or (insert your preferred DI container here) to be help handle some of the mechanics.
Also depending on exactly the sort of thing you are looking to do, the approach of embedding a macro language is potentially useful. Iron Python is easily embeddable. And Ayende wrote a very interesting book DSLs in Boo on doing this sort of thing and much more.
In my team we have hundreds of shared dlls, which many also reference other dlls that themselves reference other dlls, and so on. We have started to use a 'Shared' directory for all the dlls that we feel are generic enough to use in other projects, such as a database comms dll.
The problem is that if one of the dlls all the way down the tree is changed, then everything that references it needs to be recompiled to avoid versioning issues (which occur at runtime).
To avoid this, there is now talk of adding all our 'shared' dlls into one big assembly, and anyone creating new apps simply reference that, and that alone.
This obviously will get bigger and bigger and i'm not sure if this is the best way or not. Any thoughts please?
What we do is treat the maintenance of the shared DLLs as a project in itself, with its own source-control and everything. Then about twice a year, we do a 'release' of the shared DLLs to the public, with its own version number and everything. As long as you always use the DLLs as a 'set' (meaning all the ones you reference are from the same release) you're guaranteed not to have any dependency issues.
It's most definitely not the best way to do it. I have a few "shared" DLLs at my job that are kind of like that. They get unwieldy and difficult (read: impossible) to make meaningful changes to because it becomes too difficult to ensure that changes don't break apps downstream, which seems like the exact opposite of what you're trying to do.
It sounds like what you really need to do is separate your concerns a little bit better. If all of these DLLs are referencing each other, they're probably too tightly coupled. A true "shared" DLL should be able to stand on its own, or as part of a packet of three or four that travel as a group. If your dependencies are actually preventing you from making changes, then your coupling strategy has gone horribly wrong.
Putting everything in one large DLL certainly isn't going to make anything better. In fact, probably the opposite. Once you've got everything in one DLL, the temptation will be there to couple everything within it even more tightly together, which will make it impossible to pull things apart later.
you can make one solution that include all connected projects.
and when you need to release, just build this solution
Update.
As you say, the solution is cant hold so much dlls.
In other hand you can make an external MSBuild script
or using CruiseControl.NET that have possibilities to make such complicated tasks.
To quote from the GoF book, "Program to an interface, not an implementation." This could apply here to some of your libraries. You are already aware of how brittle your develop becomes when you have tight coupling. Now what needs to be addressed is how to give you breathing room.
You can create an interface. This will provide a contract that any application can use to specify that a minimum set of functionality is available.
You can create a Service that implements an interface. This will allow you to provide what would be thought of as an addon or a plugin. This allows you to design towards a contract version with expectations that your tools will adhere to.
You can create a Service that only uses an interface. This will allow your application to send in any concrete implementation that adheres to a contract of design.
Products like development editors and web browsers use this approach to make some code reuse possible. Thank you. Good day.
Design Principles from Design Patterns
Plugin
...if there is such a thing. Here's an image of two approachs for structuring DLLs/references in a .NET application: http://www.experts-exchange.com/images/t80668/compArch.png. The app can be a website (it is in this case) or a winform. Each box represents a DLL. For the winform app, just replace "webcontrols" with "winformcomponents".
The first (top) image is what I like. You might want to extend "some" of the base web controls and directly use others. The 2nd image makes you extend any web controls via interface. To me that seems overkill since you may want to simply use what is already there without modification. Which is better and what are the advantages/disadvantages?
The first image puts the lowest common constructs(exceptions, fileIO, constants, etc) into a common.dll. The 2nd image puts app business logic and common into one DLL. Which is better and what are the advantages/disadvantages of each apporach?
Having lots of references is usually bad because loading DLL's has a non-negligble cost. It's not as elegant perhaps, but having fewer modules improves your performance. As so often in our craft, you have to find the balance between elegance of total modularization and the harsh reality of performance. And as usual in our craft, you won't know what balance is until you start profiling to measure the performance of your application.
I think this is a really down to programmer preference.
It all boils down to dependencies really. More things in one DLL means it will naturally create many more depentdents on that DLL.
I personally tend to follow along similar lines to the MS structure, for these reasons:
It makes it easier for newcomers to the custom "framework" to find what they want (e.g. CompName.Web.UI and CompName.Data.
It helps reduce the dependencies to "obvious" choices. I am not too keen on CompName.Common type DLL's because it does not clearly indicate possible dependents, whereas CompName.Web.UI suggests that it is likely to be used by any web apps.
Obvious size reduction, since DLL content will be more "relevant".
DLL's for tiers within an app make sense, the types within should only be those types required by the business model, other objects (such as utility, data access etc.) should be in their own libraries.