Compiling forms in C# - c#

I want to compile each individual form on my application to be used sort of as a dll on its own... I looked into this and found very confusing representations of assemblies, which may or may not be what I wanted.
Is it possible to compile the form1.cs, form1.designer.cs and form1.resx to be 1 single file which then will be able to be used as a dll. I use "dll" as an example because that is the functionality I need with each of these forms when compiled to a single file, I need to be able to call it and use it from a shell application.
I know it is possible in VS to create a separate project which will compile into a dll but with something on the verge of 80 forms to compile... it will be a messy thing to maintain. So basically, is there an easier way?
this is the closest code I could get, but it is in console, so it will be impractical if there are easier ways... also I am not sure if it will actualy compile form1.cs, form1.designer.cs and form1.resx and still work as a dll
csc /target:library /out:MathLibrary.DLL Add.cs Mult.cs
Thanks for the help

Possible? Yes. Advisable? Umm, not sure.
You must study the CSC options to use it in such a massive way.
Partial classes are simply each listed among the sources. See here
The RESX file must be compiled by ResGen.exe to a resources file see here
You will use the /References parameter to include other DLLs.
The real challenge will probably come when you try to get cross references to work, depending on the layout of your application. Is there a main hub that will control all forms? Is it a plug-in architecture?
Good luck

Basically, you are working with solution. It can contain multiple projects. For each dll, you must have one project. So create 80 projects, add to each of them single form, edit it, add some logic.
Then there will be a main project, which produce exe. You can reference all dlls in that project, but better don't. If you do, updating any of dll will required recompiling that exe too. You can load them dynamically or use sort of plugin system (to enumerate dlls, understand their purpose, etc). Then you obtain Type from assembly (loaded dll), create instance (which will call constructor, which calls InitializeComponents, which loads form resources) and display form.
Regarding abstraction, you surely need something. To example, login window. You can create a generic form with some focus, user interface and user interaction logic. But it has to communicated with main project (which encapsulate encryption, password storage model, user rights, etc). One easy way to do this is to provide 2 interfaces:
interface ILoginImplementation
{
public void SetInitialUserName(string name);
}
interface ILoginLogic
{
public bool TryAuthenticate(string name, string password);
}
Implementation is what your form must implement and Logic is what main project implements and supply when instantiating login form.

I realize this is probably not ideal, but I still think your best bet is to use Visual Studio and create a separate project for each .dll to be created.
By right clicking the Solution node and selecting Add > New Solution Folder, you can at least organize your projects into a somewhat more orderly hierarchy. That alone might go a long way to make your project more manageable.
PS: If you haven't already, you should definitely try to create an interface, or a base class (or both!) that each of your Form-classes can derive from or implement. If you're able to abstract away and generalize some of the logic, it is quite likely to save you a lot of work down the road.

Related

Sharing classes between applications

I'm working on a Visual Studio solution that currently has two projects in it (with more to come later). One project is a mature C#/Winforms application that I built last year (think of it as the prototype). The other one is a DLL that is going to do the same thing as the prototype but through a different application. I'd like to re-use code from the prototype (let's call the method in question SyncInvoices() ) in the DLL because the prototype code works perfectly b/c I've hammered the bugs out of it. The class that contains SyncInvoices is baked into the prototype application instead of being its own DLL.
I've added the class that contains SyncInvoices() to the DLL's project (as a linked file, since it already exists elsewhere in the solution). I can instantiate that class in the DLL project and call SyncInvoices() but the compiler throws errors related to GUI elements.
The problem is that SyncInvoices() has some-thread safe calls to the Prototype application's GUI in it, basically used to pass messages/errors back to the interface.
The DLL doesn't have a GUI, so it doesn't need to run that code. It still builds the rest of the methods in that class, even though they aren't used. Is there a way I can tell the compiler to ignore those lines when building the DLL? I'd rather not maintain two sets of nearly identical code, especially when the two projects are part of the same solution.
I thought about using #define/ #if blocks to partition off the code but I'm not sure if C# works that way-- most of the time I've seen those used is to keep debug code from ending up in production. If it is possible to tell the app to include/exclude code through #if blocks, how do I set the values?
Should I just bite the bullet and make a copy of the method without the offending code in it?
Without more specifics it's hard to give the correct answer, but I'd say generally you'd handle this with events. Whatever calls into the GUI are happening in the prototype, that would typically be some form of event, which you would subscribe to in the prototype when you instantiate your new class.
Are there any particularly problematic cases you could give more specifics on?

Ensure only one class can access a reference dll?

I have a project where I want only one class to have access to a dll. I would be content with hiding the dll from intellisense, but still having access to it if that is an option. Either way, I want only one class to use the dll and for it not to be seen and/or accessible otherwise.
I'm using C# in visual studios.
Simply said: You can't do that (but keep reading).
Basically, a DLL (From the .NET perspective) is a bunch of code and config files. No more than that. So, given that you'll need to make public those classes in order to be used from another ones outside that assembly then you can not.
What you can do (I ended up doing this a few years ago) is to use some kind of reflection to determine which class (and namespace) is trying to access your assembly and only permit the proper one.
Other way is to implement a key negotiation between your DLL and the permitted assembly. You'll need to implement those manually, as far as I know.
Anyway, keep in mind there's always a way to bypass this kind of protection by disassembling and modifying your code. So, at least, don't forget to obfuscate the file. Anyway, this will just make it a little more painful, but still possible.
An alternate approach, if you goal is to stop people using the functionality of the dll by accident is to push your wrapper class into an intermediary assembly. Your project then references that intermediary project, rather than the underlying dll which effectively hides it. So your project structure would change to something like this:
Main Project -> references API Wrapper Project -> references API DLL
For this to work, your wrapper project needs to make sure that it doesn't accidentally expose any of the API DLL classes through its public interface.
Obviously this doesn't stop your developers from going in and adding a reference to the API DLL so that they can use the library directly, but if the goal is to stop accidental access to the API DLL classes because intellisense has helped the developer out a bit too much then it might be a viable option.

Winform application program interface "Argument type is not assignable to parameter type"

I have a Winform application where I would like to implement some sort of an interface for the customer, so parts of the code is changeable by customer later on if they need to. I believe my approach is wrong, because I get an error in Visual Studio after recompiling my Winform application. The error is "Argument type MyClass is not assignable to parameter type MyClass", but I'm still able to recompile it. I'm worried this would break later on...
This is how I have implemented it until now:
In my winform application I have created an abstract class with a virtual method.
I'm "releasing" an open source project dll assembly for the customer where this abstract class is implemented and the method is calling the base method in the abstract class. If customer would like to change the method, they simply implement it themselves.
This open source project is then referenced and implemented in my winform application.
When customer would like to change the method they implement the method, recompile the dll and replace the new dll with the one I distributed with my assembly.
My winform application has it's own strong name, and the open source project has it's own strong name.
However, when I recompile my Winform application after having referenced the open source project, i get this error: "Argument type MyClass is not assignable to parameter type MyClass". I can still recompile the project. But I'm concerned the implementation has some serious flaws and will break later on. Especially also since I have implemented WyBuild where I will distribute updates for the Winform application.
I need to provide a way for the customer to change some methods in the application without having access to all the source code. How can this be achieved if my implementation is wrong, what is your suggestion?
Thanks.
I'd say that approach itself is a bad way to do it. To me, this sound very error prone, and you state yourself that you have a bad feeling about it. If so, then really don't do it this way.
There sure is a couple of other solution thinkable, but given your descriptions I might do it as follows, which would stay your your original intention.
Have a look at Microsoft's Managed Extensibility Framework (MEF), which could help you in several ways.
Simply put, it would work like this:
You define the interface that the custumer has to implement.
The client then creates an assembly that implements exactly that interface and puts it a location that is monitored by MEF
MEF loads the assembly automatically (no need to reinvent the wheel)
MEF gives you a lot of control over how you want it to work. Like, like should it allow loading only or multiple assemblies that implement that interface at the same time, or should only look for plugins only at the start of the application or monitor the plugin location during the full life-time of it.
Also by doing it this way you get rid of the custom solution you are assembling here and instead use a mature framework that provides a standadized way to do it. Just have look at some tutorials on the net, it is really easy to get into.

What is an easily maintainable way to share a common .net class library over many corporate asp.net mvc 3 web applications?

I've been struggling to do this in a way that fulfills all of my requirements.
Here is what we have in our library:
Base classes for controllers and services
Business objects (stores, departments, etc)
Common Partial Views (Login, Error, etc)
Base class for HttpApplication
General common code (read an INI file, create a db conn, etc)
The one requirement that has been giving me trouble is as follows:
Lives in one place on a server. (i.e. copy local = false)
This breaks because:
The DLL containing the HttpApplication class must be in the same directory as the web apps dll to launch. I haven't found a way around that. I'm ok with duplicating this code in every app, but would rather not.
The shared views don't like to work if I use Assembly.LoadFrom() to load the dll from the shared location. (I've been using this method to precompile my views)
Any namespace shortcuts in web.config break at runtime with compilation errors because the web.config is parsed before the assembly is loaded.
My question to you folks is how do you handle your common code in a similar environment?
The GAC seems to be more trouble than its worth, and we want all of our apps to be using the same code, and not have multiple apps on multiple versions and have to maintain all of that. Are there design patters/best practices that can guide us in this regard?
Also, as a bonus, if you can solve any of the problems above, that would be great, too.
Thanks!
Edit: I guess a question that follows is whether or not we should even have a directory with the common dll(s) on the server, or if they should only be deployed as projects are deployed/updated?
Firstly, you will want to separate out what you're trying to achieve. Don't create 1 library that does everything or you will have a Big Ball of Mud. Don't be afraid to create several maintainable libraries to achieve what you're after. Is there a specific reason it needs to be stored in one location?
For example, several of the items you mention are MVC or web specific. If you have items that can be reused by MVC, create a class library that contains MVC base classes you inherit and reference them in your project. Use the single responsibility principle as much as possible.
Regarding the other items you mentioned, like database connectivity, if it's reusable, abstract it out in a data access class library and reference it. Other simple operations like reading an ini file or creating a file, create another library and abstract it to easy to use methods.
I prefer to copy the library dlls locally. You never know when you will need to make changes to the library, but you don't want all of your projects to stop compiling. When you're ready to implement a new version of the library, copy the dll in and recompile.
Not sure why all the hate towards the gac. It was designed to handle this specific problem. Install your common dlls to the gac and all apps can see them. Need to deploy a new one, just re-install it in one place.

How to share properties between multiple Visual Studio projects? (especially C# projects)

Keeping properties of multiple Visual Studio projects manually in sync is annoying. So, how can you share properties between multiple projects?
Edit: I refer to properties like conditional compilation symbols, treatment of warnings and errors etc., i.e., things you can configure in Project->Properties tabs or by editing the project XML file.
Similar questions have been asked before, see: 1, 2 and 3. However, in my understanding, the answers have been C++-specific. I am looking for an answer for C# projects. Nevertheless, do not hesitate to answer for other kinds of projects (Visual Basic etc.) if you keep the separation clear, because someone else than me might be interested.
This blog post proposes a solution to the problem, but I would prefer something simpler.
Also, you can at least solve a part of the problem in the following way (note that although I tested it, I did not test it thoroughly):
Create an AssemblyInfo.cs file with the assembly attributes you intend to share. Link to this existing item in the individual projects. Use the original (local) AssemblyInfo.cs and put project-specific assembly attributes there. Unfortunately, overriding attributes does not seem to work, and managing the attributes via the GUI is now limited.
For that kind of things, I prefer to have a separate Class Library Project, with one (or more) static classes storing the (static) properties. Then add a reference to that project from every project that needs to have those properties in sync, and all those projects will have the same values and you have to change it in only one place.
For example, let's say that I have the same app in web and desktop form. Things like connection strings and such will have to be the same for both. So I will create three projects:
MyProject.Web (Web application)
MyProject.Desktop (Windows forms application)
MyProject.Common (Class library)
Then I add a new static class in Common called Properties with a static property called ConnectionString that returns the connection string.
I then add a reference to Common in Web and Desktop, and when I want to access the connection string from any of them I use Common.Properties.ConnectionString.
We make very heavy use of the .vsprops files to have shared macros defined between our native projects.
Someone asking exactly the same question as you came up with the idea of adding a "blank" visual C++ project to the solution so that could import the vsprops file and the properties would be generally visible to the rest of the solution. If it doesn't sound too gross a hack, I can find out how it worked out.

Categories