Is there a recommended process for creating reusable ASP.NET assemblies that contain UserControls that can be shared across projects in separate solutions?
We have currently have a set of post-compilation steps that run aspnet_compiler.exe on the project, generate the precompiled assemblies using a given name, followed by aspnet_merge.exe to combine each individual control assembly into a single assembly - which is then copied into the bin directory for the project.
Unfortunately, user controls compiled in this manner don't 'play well' with the VS designer - and throw exceptions at design time that make working with pages that host them cumbersome.
Is there a better approach for doing this?
That is the only approach that will put them into a portable stand-alone assembly like that. Sounds like you already know everything referenced here, but this is the best article I know of that discusses the technique:
http://blogs.msdn.com/davidebb/archive/2005/10/30/487160.aspx
What I've always done is just require the ascx to exist, too. The code-behind can be in the portable dll, but still require the ascx. You can help manage duplicates by keeping them all in one place and mapping virtual directories to that location. The advantage of this approach, even though it is low-tech, is that each app if it wants could customize the ascx's look. It could move things around or change the styling, etc, and the code-behind would be none-the-wiser as long as the changes didnt affect which server controls exist.
Related
I have a solution with multiple projects each of which connects to the same DB and uses overlapping constant values that I would like to set somewhere instead of replicating manually. I have tried a variety of things online like making a custom class and linking projects to it, setting constants in a project config file (which doesn't exist like the guides claim), and so on. I've been unable to figure this out after more than an hour of searching and experimenting so if you have any ideas, let me know. The structure looks like this (the blue-underlined stuff are some of the projects in the list):
You can make another project under the solution to contain your class.
All the other projects can then reference that project, meaning the same functionality will be available in all the other projects without having to duplicate anything.
I will extend the previous correct answer with some more information.
Your solution structure is something to think very carefully as it is a combination of application design/architecture and leads to extensibillity, scalability and future maintainability.
Take for example the following article Common web application architectures.
You can see the Clean Architecture (AKA Hexagonal) which leads to specific projects withing a solution
You can see older designs where the DB access would go into a project called ..DAL
Simple projects can use the second one, more business rich ones the first or something in between.
Check this this article on shared code projects to see about net standard projects
So the above was helpful, but far more complicated than it needed to be. Apparently other answers I'd seen actually work, but it took reading a bunch of other pages to figure out the whole puzzle. The working steps are:
Create a class with public parameters for your constants
Place that class somewhere in your solution space. When I created it on the solution, it was placed in "Solution Items" in my tree (which is the root folder of the solution on the file system).
Right click each project and ADD>Existing Item and point to the class. The KEY (that was missing from most things I read) was that the "add" button" has a drop-down arrow that lets you change it to "Add as link"
In each project (after adding as link to the file), you can directly reference the values as NAMEOFCLASS.NAMEOFCONST but ONLY if you declared them as public const SOMETYPE SOMENAME. Without the const, it's not able to directly reference the value
Note that this fix is in the .sln file itself and needs to be part of the commit or it won't have any effect. It would be nice if you could use "include" or something to bring in a file a folder one level up, but here we are.
My C# .NET solution files are a mess and I am trying to find a way of getting things in order.
I tried to put all close files together in the same folder I am creating for that purpose. For example, I put interfaces, abstract classes, and all their inherited classes at the same folder. By the way - when I do that, I need to write a "using" statement pointing to that folder so I can use those classes in other files (also a mess I guess).
Is there an elegant way of doing things more clean, and not a list of files that I find very confusing?
Is it a good idea to (let's say) open a abstract class file and add nested classes for all the classes derived from it?
Is there a way of telling the solution to automatically set the folder "using" statements above every class I create?
The best way is when your solution file system structure reflects your program architecture and not your code architecture.
For example: if you define an abstract class and after have entities that implement it: put them into the same "basket" (solution folder) if they make a part of the same software architectual unit.
In this case one by looking on your solution tree can see what is your architecture about (more or less) from very top view.
There are different ways to enforce the architecture vision, understanding and felling of the code file system. For example if you use some known frameworks, like NHibernate, or (say) ASP.NET MVC tend to call the things in the name the technolgy calls them, in this way one who is familiar with that technology can easily find itself in your architecture.
For example WPF force you define in code things in some way, but also you need to define byb the way Model, ModelView, View.. which you will do intuitively in seprate files. The technology enforcce you to define your file system in way it was thought.
By the way the topic you're asking for, is broad known dilema/question, not resolved, cuase the code is just characters sequence and nothing else.
Good luck.
It sounds like you're hitting the point where you actually need to break things up a bit, but you're resisting this because more files seems like more complexity. That's true to a point. But there's also a point where files just become big and unmanageable, which is where you might end up if you try to do nested classes.
Keeping code in different namespaces is actually a good thing--that's the "issue" you're running into with the folders and having to add using statements at the top of your files. Namespacing allows you to logically divide your code, and even occasionally reuse a class name, without stepping on other parts of your code base.
What version of Visual Studio are you using? One little known feature of Visual Studio is that it can automatically create the using directive when you type a class name. That would eliminate one pain point.
If I was in your shoes, I'd start looking for logical places to segment my code into different projects. You can definitely go overboard here as well, but it's pretty common to have:
A "core" project that contains your business logic and business objects.
UI projects for the different user interfaces you build, such as a website or Windows Forms app.
A datalayer project that handles all interactions with the database. Your business logic talks to the datalayer instead of directly to the database, which makes it easier to make changes to your database setup down the road.
As your code base grows, a tool like ReSharper starts to become really important. I work on a code base that has ~1 million lines and 10 or so projects in the solution, and I couldn't live without ReSharper's go-to-file navigation feature. It lets you hit a keyboard shortcut and start typing a file name and just jump to it when it finds a match. It's sort of like using Google to find information instead of trying to bookmark every interesting link you come across. Once I made this mental shift, navigating through the code base became so much easier.
Try using multiple projects in the same solution to bring order. Seperate projects for web, entity, data access, setup, testing, etc.
IF the files are in the same namespace you won't need a using statement. If you're breaking your code into multiple projects you'll need to reference the other projects with using statements.
Its up to you. Break things apart logically. Use subfolders where you deem necessary.
Not sure.
Yes, but you'll need to create a template. Search for tuturorials on that.
1) Your solution folders should match your namespace structure. Visual Studio is set up to work this way and will automatically create a matching namespace. Yes, this requires a using for stuff in the folders but that's what it's for.
So yes, group common stuff together under an appropriate namespace.
2) Yes, subclasses should probably live in the same namespace/folder as their abstract base, or a sub folder of it. I'm not sure if you mean all in the same file? If so I would say generally not unless they're very very simple. Different files, same folder.
3) Not that I'm aware of. If you right click the classname when you use it you can get Studio to automatically resolve it and add a using (Ctrl + . also does this)
I have a fairly simple console app that monitors an exchange mailbox, picks particular emails out, and updates a couple of databases based on the contents.
I would like to implement a couple of similar systems. While it would be very simple to duplicate this system, I am looking at a more sophisticated solution - mainly an intellectual exercise, a learning exercise.
I would like to build a core application that pulls template information periodically from a DB; this information would tell the app that is has to monitor a given mailbox for emails with given characteristics at a particular interval.
I envision creating a master template (assembly) with some virtual functions (pre-processing, process items, archive items, send notifications etc). In turn, I'd create any number of templates that implement the interfaces in the master template, but the functionality could differ wildly in each case, one may update a database, while the next might store something in a file system.
My first question is whether this is a sensible implementation?
My second question is how to dynamically reference each template, and how would I call the methods of these templates at the appropriate time?
If I were to extend my Templates project, adding a new class for each new template required, I'd overcome the problem of dynamically referencing the templates. But if I wanted to keep them in separate assemblies.. Is there a way to just drop them into the project? Don't forget, the templates will be listed in a DB, so the app will be aware of them, but how to make use of them...
UPDATE:
I've figured how I can dynamically reference each template class; it requires me to supply the Assembly-Qualified Name to GetType:
I've tried to dynamically generate the template in the main app:
string aqn= "MasterTemplates.TestTemplate, TestTemplate, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null";
MasterTemplate mt = (MasterTemplate)Activator.CreateInstance(Type.GetType(aqn));
So if I keep updating my MasterTemplates project, adding in new classes as necessary, I can achieve what I am aiming for. However, how can I handle different template assemblies?
In the meantime, I'm shortly going to look at DBM's suggestion of the Managed Extensibility Framework.
Conclusion:
I don't have the time to fully investigate MEF; though it's overkill for my current needs, it looks extremely promising. And I haven't figured how to easily develop and use different assemblies for different templates - instead I am keeping all templates in one assembly, which I will have to recompile and up-date each time I require a new template. Not quite as sophisticated as the MEF alternative, but simpler and suited to my current needs.
You could use MEF to dynamically load plugins. It's in-the-box in VS2010, and works great for dynamically loading assemblies.
When using activator with a string, use the Activator.CreateInstance(String,String) overload.
Alternatively you can create an instance of the type and use it like that:
Activator.CreateInstance(Type.GetType(templateName));
How should I divide source files into projects (within one solution) to
be able to use common classes in more relatively independent apps,
avoid lots of dlls needed (preferably all in one file for each application),
keep it fast?
There are working (data processing) classes, User controls, some utility classes and Forms of the application.
You can make a separate assembly by creating a class library, and use that library within other projects within your solution. Just put your reusable classes within a class library project, and add a project reference in your applications to that library.
Each time you separate out code into a separate (reusable) assembly, it does add one extra DLL (the class library project) as a requirement at runtime, but this is very minimal.
There are no real (significant) changes to performance when doing this. It is a very common practice.
You should make Class Library project(s) for each logical unit of classes, then add references to the libraries in each project that uses them.
For example, you could have a Common library that contains basic classes used by everything else, and perhaps a Controls library that contains user controls.
Each logical unit of classes can go in a namespace within the same library or in a separate library; you need to decide which.
It would be a good idea to drop the second requirement of avoiding lots of DLL's. If you put your common code into a single "common" DLL then you need to recompile every time any class is added or modified. This could then give you a terrible versioning problem that is worse than managing lots of DLL's.
You should group your common code, by the functionality they provide, into separate DLL's. So one for data access, one for user controls, one for each type of utility function, etc. Then if you have web service that accesses data you won't need to recompile the service when you add a new user control to a single DLL. Only those apps that depend on the change will need to be recompiled.
You could put the common classes into one assembly (say CommonUtils) and then use namespaces inside for the groupings to indicate how they are split
We are developing two versions of an application. Not in the sense of a lite vs standard version of the application, where one version will have limited functionality etc. We will actually be displaying different types of information in the application, depending on the version (that's the best way I can describe it without going into too many details).
To differentiate the two versions of the application we've considered using the conditional attribute and the #if directive (if there are any other options or better way than these two, I'm open for suggestions). After some research and debate, we've decided to go with the #if approach, since this will not include the unnecessary code during the compile process (whereas the conditional attribute will just remove the calls to the methods that do not meet the condition, but still include the methods... if I'm not mistaken). I realize the two are not mutually exclusive, so we could always mix and match if need be.
Anyway... What we're now wondering, is if there is a way to only include certain windows forms during a compile, based on which version of the application we are compiling. We have split out all of the logic, so the forms are really just forms, with very little code inside them (mostly just calls to form manager classes that handle all of the business logic). The form manager classes will contain some of the #if statements inside of them, so the code can be reused in both versions of the application, whenever possible (instead of making two classes and putting a conditional attribute on the classes... though maybe this is something we should consider).
Is anyone aware of a good way to do this?
TIA
UPDATE:
Just an FYI of what we actually decided to do. We put the different versions of the forms into separate namespaces and then only had to use an #if statement around the namespace using statement at the top of the class that manages all of the forms. Worked out pretty slick and was very litte work.
I do this with library projects. I produce another project (.csproj), and then include into that project the existing sources. In VS2008, right click on the new project, Click add Existing Item... and then instead of clicking Add, use the select arrow to select "Add as Link".
Rather than duplicating source modules, Add as Link will include a reference to the existing source, into the new project. This way you can have N projects, each with a different combination of source modules. I use this in concert with #if statements within the source of common modules to produce different versions of a library.
Add Existing Item http://www.freeimagehosting.net/uploads/th.eff09391e9.png
full image
Add as Link http://www.freeimagehosting.net/uploads/th.f12b764887.png
full image
Another way to do this is using OO inheritance: put functionality that's common to both versions in a superclass, and then create separate subclasses which define the specializations of the superclass for each of your versions.
You can then build your superclass[es] as a shared library, and build each specialized subclass in separate assemblies (which reference the common shared library).
Doing this uses no conditional compilation nor conditional build options.
The solution suggested by ChrisW is probably the correct way to do it. However, it may involve a lot of changes to your design, so here is another one : instead of having several configurations for the same project, create another project with the same sources. To do that, the easiest way is to create a copy of your .csproj file and include it in the solution