I have a question regarding the C# code generation capabilities of Enterprise Architect.
How is it possible to add "using" statements?
Say if we want to have System.Thread as a namespace in our file.
Where do we specify this in the model?
I already tried to backward engineer the code with an inserted "using System.Thread", but could not detect this information anywhere in the model.
You don't add the "using" statements explicitly, they are inserted implicitly by the code generation facility where needed (the same applies to "imports" in Java). EA works it out by determining whether the referred class is in the same package.
If you want the exact details on how it does so, the code generation scripts are actually available for reading and editing (not recommended!) from Settings - Code Generation Templates. Select the language in the upper left corner, then start reading from the "File" script, which is the one that calls all the others. This is not an errand for the faint-hearted, but it's there if you want it.
I'm not sure whether "using" statements are generated correctly for classes which you'd normally consider part of standard libraries, such as System.Thread. You may need to add a System package with a Thread class in it (in a separate namespace) to get that to work properly.
Related
I'm going through this C# intro tutorial by MS, and in the section "Fix the "format" error" I'm supposed to delete code in the namespace, but I'm not seeing that namespace since I'm in the "top-level statements" mode. How do I reveal the boilerplate code that is underneath?
As described by Top-level statements - programs without Main methods:
Starting in C# 9, you don't have to explicitly include a Main method in a console application project. Instead, you can use the top-level statements feature to minimize the code you have to write. In this case, the compiler generates a class and Main method entry point for the application.
Here's a Program.cs file that is a complete C# program in C# 10:
Console.WriteLine("Hello World!");
Top-level statements let you write simple programs for small utilities such as Azure Functions and GitHub Actions. They also make it simpler for new C# programmers to get started learning and writing code.
This means that the Top-Level statements is a feature of a comiler, not of the editor. The Main method and the class (things you call "boilerplate") are not present in the source code - they are generated by the compiler.
Adding to the above answer is its Compiler feature.
The compiler generates a method to serve as the program entry point
for a project with top-level statements. The name of this method isn't
actually Main, it's an implementation detail that your code can't
reference directly. The signature of the method depends on whether the
top-level statements contain the await keyword or the return
statement.
The following table shows what the method signature would look like, using the method name Main in the table for convenience.
Reference:
https://learn.microsoft.com/en-us/dotnet/csharp/fundamentals/program-structure/top-level-statements#implicit-entry-point-method
Whoever updated the tutorial to .NET 6 with top-level statements (see the commit) forgot to update the part in question. To see the full previous version of the code you can switch tutorial to VS 2019 version either by using dropdown at the top of table of contents:
Or just by following this link.
The previous version also should work, you should be able to replace the contents of your Program.cs file with code from this section and proceed with tutorial from here.
Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 5 years ago.
Improve this question
Well, first excuse me if this is not the place to do so. This is not really a question, but I got exposed to that problem, and was pretty hard to find necessary information, so I thought would be good to make a subject just for it.
This is in attention to people with a "beginner/average" level in C# like me, so please if you have some comments or corrections to make please you are welcome.
It is around a year I was developping my project, using a lot classes. But I began to meet problems when I wanted to externalise some functions.
Why externalise my functions? In order to make support easier. In fact, creating an external LibraryClass (.dll), if in future I may make some modifies on it, and send an upgrade to customer, I only need to modify, and send that library, and not all the code.
The problem is when I want to use my classes from these libraries : It is just not possible.
Then a stackoverflower (thanks Simone Sifani) gave me the good idea : I may externalize all my classes in different projects(one project for each class).
In my case the thing became a bit difficult because all classes use each other... so I will explain how I proceeded.
1) make obviously a copy of your solution before beginning, so if you do something wrong, delete all then restart(and very good exercise to understand good how these references work, after one or two tries, you will all understand).
2) Add a Project in solution for each class you want to externalize (Right click on solution/Add new project/Class Library), then check directly the version of Framework to have the same version in all solution(in my case .NET Framework 4.6.2). If you don't, you will have no error message but debugging will not work without necessary an explaination.
3) Copy/Paste all the code of the original class in the new corresponding ClassLibrary. Then add the "public" word before each class definition.
class Myoldclass
{
...
}
becomes
public class Myoldclass
{
...
}
4) Add references (this is the longest part).
Each class may require different references :
- To .NET Frameworks
- To other classes(From now I will not use the word "class" but "Library")
I personally did the following :
4-1) put in commentary all the code that requires to use external libraries, so now you will have only errors regarding references missing on .NET Assemblies and some "unexisting functions(the ones I just put in commentary).
I also advise you to take a piece of paper, in order to write for each library, the list of references needed.
4-2) Add all references to necessary .NET Assemblies (for me was the longest part of the job). After that, you may have only errors regarding non existing functions.
4-3) Begin to compile all of your libraries that don't need to use any external library. It will then generate a .dll file in its directory (bin\debug directory). I will call it Library1
4-4) In all libraries that need to use Library1, add a reference to the libraries(Project/Add/Reference/Projects->Library1.dll file). So now all the code requiring Library1 may work correctly.(I will call that one Library2)
4-5) Once you think Library2 has references to all necessaries libraries, you can uncomment your code. For this I have two solutions : Just make Ctrl+Z until the code comes back to step 3. Inconvenient is sometimes VS found errors where there are not so you need to restart it, and so coming back is impossible.
In my case, I just opened my old classes, and overwrite all the code of my library, rewrite the "public" at class definition... and then start debugging to generate the Library2.dll file
4-6) Continue so on until all libraries get all references ok(that's why it is important to write on a paper, so by elimination, you will first debug the libraries having few references needed, and finish with the most difficult ones).
4-7) On your main project, add references to all previously generated dlls.
That's all, after it for my part my project is working as before(still have some problems to read Application parameters but I am on it). I have 13 Class Library projects in my solution, that I can debug separately, and everybody can use anybody :)
Hope that post will be useful to somebody, and if stackoverflowers want to help/correct I will try to keep it updated.
What is the point of creating as much projects? In most cases I do need a "Common" library and sometimes a library for DTO. Anyhow the main reason to move out those classes into a separate project is to minimize dependencies and to avoid polluting some of your layers...
In general I use these layers/projects:
- domain classes and domain logic with domain services - here I define also interfaces, which get's implemented inside service layer
- DAL (which is actually an ORM) - so here due mapping (or due domain classes being entities) we got a dependency on the domain classes (project)
- service layer - depending on both of the 2 projects above
- presentation (application) layer - where all your projects are referenced...
Mostly I do have a solution with 6-15 projects: 4 of them are based on the layers described above, but I do got additional ones, like domain events, domain event dispatcher (for the given DI used in the project), special libraries like HTML/PDF generation or email sending (with custom logic/templates), HttpClient libraries (spacial library to create and set up chain of handlers to do: auto-login, auto retry on HTTP 401, auto-retry on some errors or logging)...
So in short: as you see, most projects I add do have a function to fulfill. They're not class based. And there's a "polluted" project with a lot of extension and utility classes, where I do try to keep things tidy by trying to keep the classes in folders, giving them meaningful names...
In your case, if those class libraries are really re-usable, i'd possibly create them as a separate project and NuGet's. But if reuse is the goal, you need to strictly hold on some SOLID rules, otherwise a change in those classes for some feature in project A can easily break your business logic in project B.
Background
I am converting the TreeViewAdv(TVA) project on SourceForge to vb.net. Thus far I have successfully converted the code, successfully built it, added a reference of the dll to a new project, added the control to the toolbox, added the control to a form, and modified the controls properties. I have also coded functionality into the form prior to building that accepted the Aga.Controls namespace.
The Problem
When I go to debug the application that I have placed the TVA control in, I get the error: ''Aga' is not declared. It may be inaccessible due to its protection level.' on all calls to that namespace. So, I researched this problem on SourceForge and there is a thread here: https://sourceforge.net/p/treeviewadv/discussion/568369/thread/005e61ef/ that discusses this issue. Supposedly somebody figured out what the problem is when you are seeing behavior like this, but failed to share any details of their wisdom. The general issue is that when referencing a dll compiled in 2008 in a 2010 project 'is that VS 2010 requires you have Designers separate from the main assembly.' I tried contacting people there, but there seem to be no real activity on any thread in the forum at all. That leads me to my first question...
The Question(s)
1.) Hoping beyond hope, is there anybody on StackOverflow that has successfully done this for the treeviewadv project specifically? If so, I would really appreciate either a somewhat detailed description of what was done, or a short description with the final resulting code/fix. While I understand this is highly unlikely, I thought I would ask before asking more general questions on 'how to'?
2.) Barring anybody that fits the bill for number 1, is there anybody that has knowledge of this general process and at least enough knowledge of the TVA project and desire to work with me on this endeavor?
2.) Barring 1 and 2, is there anybody that has done this with any project and can either describe the general process in relative detail, and/or point to example code?
3.) Barring 1, 2 and 3, is there a particularly good resource that I can access that outlines how to update a VS2008 project in the manner described above?
Disclaimer
I understand that this process might be too involved to discuss here, so am willing to take the discussion/effort elsewhere if needed. If someone of category 1 or 2 can (answer my question/work with me on this) and you feel the discussion should be taken elsewhere please inform me as to how we can contact each other as there seems to be no formal mechanism on S.O.. I am still interested in posting (or linking) the results here for all to share if an answer can be found.
Here is a bit more info addressing the general issue of a Designer in a different assembly. There are some caveats: first I (we?) are not sure that the core problem as to do with a UI Designer. Given the project appears to be a custom TreeView, it seems likely to be the case, but the term 'Designer' could be used in a more generic fashion for this control. A second caveat is that all I have to go on is the description above and havent seen the code for the control.
That said, I am just finishing a drop in UnDo Manager component (ie it inherits from Component and sits in the form tray). Part of what it needed was a way for the dev to select controls on the form to be subject to UnDo. The layout/construction is this:
Imports Plutonix.UIDesigners
Namespace Plutonix.UnDoMgr
Public Class UndoManager
Inherits Component
Implements ISupportInitialize
Private _TgtControls As New Collection(Of Control)
<EditorAttribute(GetType(UnDoControlCollectionUIEditor), _
GetType(System.Drawing.Design.UITypeEditor))> _
<DesignerSerializationVisibility(DesignerSerializationVisibility.Content)> _
Public Property UnDoTargets() As Collection(Of Control)
Get
Return _TgtControls
End Get
Set(ByVal value As Collection(Of Control))
If value IsNot Nothing Then
_TgtControls = value
Else
_TgtControls.Clear()
End If
End Set
End Property
'...
The <EditorAttribute... decoration specifies that this component uses a special designer called UnDoControlCollectionUIEditor. If the project you are converting does not have this on one or more properties, the issue may not be related to UI designers.
Later, there is the UI editor for the COntrols collection editor. This is a separate class though it is in the same file:
<System.Security.Permissions.PermissionSetAttribute( _
System.Security.Permissions.SecurityAction.Demand, Name:="FullTrust")> _
Public Class UnDoControlCollectionUIEditor
Inherits ControlCollectionUIEditor
Public Sub New()
MyBase.bExcludeForm = True
MyBase.bExcludeSelf = True
' create a list of supported control TYPES
typeList.Add(GetType(TextBox))
'... 9 more lines adding control types to List(of System.Type)
End Sub
End Class
Nearly all the code resides in the base class ControlCollectionUIEditor which is in a different assembly (a DLL). My component though is actually using one defined locally, so as a test, I changed the editor to use to ControlCollectionUIEditor which is the base class in my designer DLL. Labels, panels, GroupBoxes etc dont have/need UnDo capability so my Designer exempts them from showing in the Designer - when I use the base class, they all show up in the designer list as expected.
ALL the standard UI Editors (String Collection Editor and the like) are in NET assemblies, so are defined in one assembly and used in another (yours/ours/the devs). A few years ago, I decided to put several different UIDesigners I had written into a UIDesigner.DLL (ie their own assembly) and they worked fine.
Beyond that, I am confused on some specifics. It sounds like you are trying to use this 2008 assembly (a DLL?) in your conversion. Is that where the designer is? If so, it is already in another assembly from your VS 2010 project, so why is there an issue? Can the whole thing be avoided by also converting whatever is in this 2008 assembly (still not clear on what is in it).
HTH
EDIT
I had a quick look at the source, and it is using at least 1 UIDesigner. TreeViewAdv.Properties.cs defines NodeControlCollectionEditor as a custom controls collection editor for the NodeControls property. The Editor is in NodeControlsCollection.cs. Coincidentally, it is doing EXACTLY what my UnDoManager does: define what control types are valid for a CollectionEditor. Your thing then calls the standard NET CollectionEditor, mine calls the CodeProject DialogForm version. There is also a StringCollectionEditor.cs file but I cant tell if that is a UI Designer or something for the user at runtime.
Since you have the code for these, you should be able to mimic something like what I did above. I would also verify that VS 2010 does indeed have the quirk mentioned. But I am also confused what is in the 2008 assembly. Is there some piece that you dont have the source for? You might also try adding the security attribute to any UI Designers in the project since the CS version does not have them and the msg quoted indicates something about 'protection level'. It seems unlikely to help, but since you are dealing with a quirk, who knows...?
Also, that is a pretty ambitious conversion project!
Cause of Problem Verified
First, I would like to point out that indeed, the issue of losing track of the namespace in the referenced dll was because of the presence of custom UI editor/designers in that dll.
The Fix
The general process of separating Custom Editors/Designers from a 'primary' class library is this:
1.) Find all custom editors/designers in the project. If you are only somewhat familiar with the project, a good way to do that is to Find (Ctrl + F) 'UITypeEditor' in the entire solution. If you are the one who designed it, then you should have no problem.
2.) Delete or comment out the entire custom editors/designers class(es). I prefer commenting out for easy documentation (just in case you need to go back).
3.) Create new project in solution. If you cannot see the solution (i.e. you can only see the project) go to tools-->options-->Projects and Solutions. There you will see a check box that says 'Always show solution'. After revealing the solution, right click and select add-->New Project... Can be named whatever, that will have little to no effect on the code.
4.) Within the new project rename Class1 to whatever is convenient. Transfer all 'using' statements at the top of the files that originally held the custom editor/designer classes. EDIT: Add using statements for any namespaces that would allow you to access the types needed from the primary project. Declare the appropriate namespace for each class. Copy and paste custom classes into correct namespaces (You can, if you want, place ALL of your custom editor/designers in this one file). Change any classes that are declared as 'internal' to 'public' (internal is only the scope of the assembly).
5.) If the new project requires any references, add those now. If your custom editor is editing custom types, you will likely need a reference to the project that defines those types. If those types are defined in your 'primary' assembly this can get a bit tricky as it could cause a circular reference issue. One way to get around this, and probably the right way, is to remove the declaration of those types from your primary assembly and create a new project/assembly just for their declaration. If they are, for some reason, inseparable from your primary assembly, set aside a successful build (dll) previously made of you primary assembly and reference that. This reduces future sustainability of code as those types may chance, but gets the job done now if that is what you want.
6.) After debugging the custom editor/designer project, build it and add that project's build (dll) as reference in the primary project/assembly.
7.) Debug internally, create a new project in solution and add BOTH dlls (Primary and Custom Editor) to the references. Verify controls/properties behave as they are supposed to in both design time AND run time.
8.) Finally, debug externally. Create new solution, reference both dlls, verify functionality. It may seem overkill to debug in both the native solution and externally, but I found many differences in behavior between the environments. Be thorough.
Important Note: I spent a LONG time figuring that both dlls needed to be added. You see, when adding just the primary dll to the test project, it would act as though BOTH were added. I though this was reasonable (& quite dandy) as the primary assembly references the other assembly. However, close and open Visual Studio and it does not work. Long story short add BOTH dlls.
TreeViewAdv Specifics
1.) There were two Custom UIEditors. The first is in NodeControlsCollection.cs called NodeControlCollectionEditor, which inherits the standard .NET CollectionEditor. The only functionality added was the explicit assigning of what kind of controls the editor is allowed to work with. It seems this was largely done as a workaround to allow ALL NodeControl types to be added to the collection (this required the passing of type NodeControl), but get around the fact that passing the NodeControl type causes an error because you cannot instantiate an abstract type. The second is StringCollectionEditor in StringCollectionEditor.cs. This also inherets the standard .NET CollectionEditor and adds a little functionality (Not sure of the purpose).
2 - 4.) Same as the general process.
5.) I currently had to use the latter method (setting aside a dll of Aga.Controls for my custom UIEditor to reference). Later I hope to separate some of the object declarations from the primary assembly to make the solution more reliable.
6 - 8.) The original bug (losing the aga namespace) did not occur when running the testing application inside the same solution (even if different project). Additionally, some fixes that worked externally did not run correctly internally and vise-versa. Thus, my advice for testing in both environments.
Final Request
While both the general and specifics of my question is answered here, Plutonix's help was vital in my coming to the solution. While I am marking this as the answer. I would like if people also upvote Plutonix's answer given the effort that he has put forth in helping me find the answer (in addition to the fact that his answer is also correct if less specific).
EDIT: The process outlined above worked when I was modifying the original TVA C# code. I was even able to reference and successfully use the resulting DLLs in a VB.net project. When I tried to apply the same process to the TVA code line that I had converted into VB.net, it resulted in the same problem that I started with. Everything works until I go to run the application and then it loses sight of the aga namespace.
EDIT SOLUTION: Go to properties (of project losing reference)--> Compile tab --> Advanced Compile Options button. Under target framework, change to ".NET Framework 4" if not so already. If that value is already selected, you are likely looking at a different cause.
I have a class library and am using only part of it. Is there a need to delete what isn't being used in order to shrink the size of the created code (in release configuration)?
As far as I've seen, the compiler takes care of that, and removing the code doesn't change the EXE file size. Will this always be true? Removing all unneeded code would take very long, so I want to know if there's need for that.
More information: there are methods and classes in the class library that aren't called from the executing code, but are referenced by other parts of code in the class library (which themselves are never called).
No, the compiler includes the "dead" code as well. A simple reason for this is that it's not always possible to know exactly what code will and won't be executed. For example, even a private method that is never referenced could be called via reflection, and public methods could be referenced by external assemblies.
You can use a tool to help you find and remove unused methods (including ones only called by other unused methods). Try What tools and techniques do you use to find dead code? and Find unused code to get you started.
It all gets compiled. Regardless of whether it is called or not. The code may be called by an external library.
The only way to make the compiler ignore code is by using Compiler Preprocessor Directives. More about those here.
I doubt the compiler will remove anything. The fact is, the compiler can't tell what is used and what is not, as types can be instantiated and methods called by name, thanks to reflection.
Let's suppose there is a class library called Utility. You created a new project and added this class library to that project. Even if your EXE calls only 1-2 methods from the class library, it's never a good idea to delete the unreferenced code.
It would go against the principle of reusablity. Despite the fact that there would be some classes present in the library unreferenced from the EXE, it would not have any bad impact on performance or size of the program.
Determining all and only dead code is (if one makes the idealization that one has a "math world" like language) recursively undecidable, in most languages. (A few rare ones like the Blaise language are decidable.)
to the question of whether there is a "need to delete what isn't being used in order to shrink the size of the created code": i think this would only be useful to save network bandwidth. removing unused code is crucial in web applications to improve loading speeds etc.
if you're code is an exe or a library, the only reason i see to remove dead code, is to improve your code quality. so that someone looking at your code 2 years down the line won't scratch their heads wondering what it does.
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