Keep a specific "using" statement when cleaning up code - c#

I am a huge fan of keyboard shortcuts. I am especially fond of Remove and Sort Usings in Visual Studio. Until now, I had no reason to question the use of such a command. I recently discovered that a using statement existed in several files but was not actually used at all in the files. I had no problems letting the command wipe it from my view until I tried to update service reference and discovered that some properties could not be serialized. using System.Runtime.Serialization; would allow the classes in question to be reflected with whatever magic was required to update the service reference. Having added this line back into several classes, teaching several people I work with shortcuts to help keep their code clean, and general forgetfulness, I can see this line being removed at some point in the future and someone new wondering why things won't serialize anymore.
Is there an attribute to attach to this statement that can keep it from being removed by auto-formatting techniques?
EDIT
My mistake in the description. The service reference could not be updated because the service itself could not start. When attempting to start it, and error in the Event Viewer stated that the service could not be started due to new properties of the class not being serializable. The class being the first one to attempt serialization - fix or remove the code in question and the next class would appear in the next error log. I discovered, by examining other classes, that the difference between those not being serializable and one being serializable was the classes that couldn't were missing the line: using System.Runtime.Serialization;

Related

Is it possible to add C# classes immediately before compilation in Visual Studio

Now I programmatically generate sources and create some classes before compilation and obviously add it to project in solution. Maybe it is possible to "silently" add classes before compilation without creating .cs files in disk and not showing these classes in Solution Explorer (maybe using Roslyn).
EDIT: I must not use any runtime code generation.
You can put the classes in a separate DLL (class library). When you create that DLL using another solution you will not see the classes in your solution explorer of the project where you include them.
Don't forget to add a reference to the DLL (class library) in your main project.
You could probably do something with MSBuild, creating a custom project target which does the work, but I've never done this.
What I have done recently which is now achievable on the DNX-based ASP.NET 5 platform, is a concept known as meta-programming. I've written a blog article about this concept specifically with examples of generating code at compile time. In my particular example, I've got a class that won't compile, but then with an introduction of an ICompileModule, I can fill in the missing method return statement at compile time.
This is possible because in DNX-based applications, the RoslynCompiler class actually supports loading instances of ICompileModule at compile time, and then running these instances before your main project compilation. This enables you to add/remove/replace syntax trees in the compilation before the compiler finishes its work.
If you're looking to develop on ASP.NET 5, this could enable you to do what you need, but I don't know how you would go about doing this otherwise.
Seems quite aspecty to me.
I asked a question which I also answered myself about engineering a compile-time solution that performs code generation for another scenario:
Getting interface implementations in referenced assemblies with Roslyn
And lastly, other examples where this might be useful, and something I've been toying around with, is the ability to generate EF-style migration classes from .sql files embedded in my assemblies. All these scenarios are now easier for me to implement on ASP.NET 5 + Roslyn.
Without knowing your use-case properly, here's an idea...
Create a VSIX that listens to an 'on build' event
Upon initialisation of the build, the VSIX creates your new classes*
The same VSIX will also listen for a 'build complete' event
Upon completion of the build the VSIX would tear down the new classes
*Your question states that the classes should not be created on disc, so the VSIX could
create the classes as a memory stream (?)
add the new class as code within existing files on disc
create the new class as a new file on disc (or cloud ?) in C:\Temp or elsewhere
the new class could be part of a partial class (either a real partial class in your application or an empty new dummy partial class)
In any case the project file would need to be auto-edited (by the vsix) to reference the new file(s). Presumably you want the project file reverted aferwards ?
And if, unlike me, you want to get down and dirty, you could always interfere with the IL, but you're on your own there !
As TarkaDaal says, without knowing why you need this it's not easy to provide a more definative answer.

Separating Designers from Main Assembly

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.

Force Pex to ignore generated code, can I do it without a reference to the Pex assembly?

I'm trying to start using Pex, and I have certain code that I want it to ignore testing.
I create configuration sections for config files using the Configuration Section Designer addin. Unfortunately the code generated is not quite perfect, because it doesn't do tests for nulls and other nice checks. However, for now at least I want the code to be ignored when running pex explorations as I can't change the code without it being overwritten in future, and it's a known fault that we can work around.
I found the PexInstrumentMarkedByand the PexCoverageFilterMarkedBy attributes, which seem like they may do the job (of ignoring code with the GeneratedCodeAttribute), but as far as I cam see I would need to put those in my assembly, and thus have a reference to the Pex framework in my operational assembly... not going to happen.
Does anyone have better ideas?
I know this may not be an option, but here is a suggestion - If I understand your question correctly, the only code you trying to avoid is the designer generated code. Since there is no way you can reference Pex assembly in your operational assembly, would you consider an alternative approach to creating Config Sections, i.e implement them as you would normally do.

db4o How to rename class via configuration

I am using db4o in two seperate projects that share the same classes but not the same .dll . I am fixing this so that they share the same .dll but I need to rename the classes. According to the documentation you set up configuration and open the db with the renames and it updates everything. I have tried this but when I try to open the DB the project just hangs. Am I missing something here
config.Common.ObjectClass("DllName.Old, DllName")
.Rename("NewDll.New, NewDll");
var db = Db4oEmbedded.OpenFile(config, DBFile);
That looks correct to me and should work. It really should work when the class-names and assembly names are correct. The class is not a generic class, right?
You don't get any exception, right? Is db4o just hanging or actually doing some work?
Edit: I could reproduce a stack-overflow exception with renaming a class. Maybe you are running into a stack overflow exception as well, but you cancel it before it actually happens?
Anyway, I created a bug-entry in the db4o-bugtracker.
I was successful with the following answer:
https://stackoverflow.com/a/1138178/541420
Very buggy otherwise though :(

WCF error service error message with shared classes

Source code:
http://code.google.com/p/sevenupdate/source/browse/#hg/Source/SevenUpdate.Base
SevenUpdate.Base.Sui cannot be used since it does not match imported DataContract. Need to exclude this type from referenced types.
Now I tried unchecking reuse reference types and I was able to get my project to compile. but when sending a collection from the client it was never received or couldn't be deserialized on the server end.
I really need this to work. Any help would be appreciated, the fullsource code is provided by google code.
I didnt download the source and build it, but could it be that you are missing DataContract on this class? Sui class has a property of type Sua as DataMember so it will need to be serialized as well. It looks like this in your code currently
[ProtoContract, ]
[KnownType(typeof(ObservableCollection<LocaleString>))]
public class Sua
What would I need to do to reproduce this error? The first bit (about matching data-contract) sounds like WCF isn't very happy with you, which suggests you have two similar (but different) contracts "in play". If you are re-using the types from a shared library this shouldn't be a problem.
If you do end up excluding the types (and having a different model at the client and server) then it can get a bit tricker, since "mex" doesn't guarantee the positions will remain intact (and indde, they regularly change) - but you can fix this in a partial class, by using a few [ProtoPartialMember(...)] against the type (not pretty but it works).
But I stress - the main problem here seems to be WCF; if that isn't happy such that the code doesn't codegen / compile etc, then my hands are fairly tied (since it won't get as far as talking to protobuf-net).

Categories

Resources