Can I do a conditional compile based on compiler version? - c#

I am maintaining .net 1.1 and .net 3.5 c# code at once. For this purpose I created two csproject files, one for .net 1.1 and another for .net 3.5.
Now, in my source code I am adding new features that are only available in .net 3.5 version, but I also want the code to compile in VS 2003, without the new features. Is there anyway to do a conditional compile based on the compiler version?
In C++ I can do this by checking the value for the macro _MSC _VER, but I am looking for an C# equivalent.

You can define a different symbols in each CSPROJ file and refer to those in the C# source.

If you can keep the 3.5 specific code in separate files, you could simply split the file allocation between your two .csproj files (or use 2 different build targets in NAnt) - too bad partial classes only came around in 2.0, or that would make it easier to spread the code around...
If you need to mix the code at the file level, the [Conditional()] attribute can filter out entire methods, but I'm not sure if the compiler will still try to process the code in the method. MSDN says the code won't be compiled into IL but parameters will be type checked, but I haven't tried it out. More info here: http://bartdesmet.net/blogs/bart/archive/2006/08/30/4368.aspx and the MSDN link is here: http://msdn.microsoft.com/en-us/library/system.diagnostics.conditionalattribute.aspx
If that's possible, since you've got 2 project files already, you can specify a different define in each one to set the version - no need to look for a macro when you can make it yourself.

Related

Can multiple .vsix with VB/C# Diagnostic Analyzer/CodeFix/AutoUpdate cause performance issue?

I'm implementing a system that will implement code quality as part of in-house quality measures. I've structured the system in two possible ways of implementation as follows:
Implementation 1: (Already implemented)
An AutoUpdate extension (Stub)
C# CodeQualityPlugin (Roslyn C# Diagnostic Analyzer & Code Fix)
VB CodeQualityPlugin (Roslyn VB Diagnostic Analyzer & Code Fix)
The AutoUpdate feature checks for any update of itself and other CodeQuality plugins by verifying their version number. It halts update for the next 7 days once the CodeQuality plugins are updated.
This is presently my idea of implementation, but the development is halted citing the possible performance issue related to number of extensions in this implementation and that there might be a Visual Studio limitations in its usage/performance (as mentioned by the team)
Implementation 2: (Suggested)
C# CodeQualityPlugin (Roslyn C# Diagnostic Analyzer, Code Fix, AutoUpdate)
VB CodeQualityPlugin (Roslyn VB Diagnostic Analyzer, Code Fix, AutoUpdate)
In this the update functionality is individually triggered and maintains the single responsibility philosophy.
I'm not sure if the AutoUpdate project (Which uses the menu command template) and C#/VB CodeFix/DiagnosticAnalyzer project (Roslyn Template ) can co-exist?
Implementation 3: (One of the opinion)
CodeQualityPlugin (Roslyn C#/VB Diagnostic Analyzer, Code Fix, AutoUpdate)
I'm not even sure if these three can co-exists in a single vsix.
So my question what could be the performance issues in the above three scenarios, and how do we implement the plugin that we develop based on the Roslyn template into a normal menu command template extension for visual studio.
---EDIT---
To summarize the requirement was as follows
Coexistence: VSPackage extension (to extend shell command component of Visual Studio) and Managed Extensibility Framework/MEF extensions (to customize and extend the editor to include Roslyn DiagnosticAnalyzer/CodeFix), should coexist either in
Single VSIX
Maximum 2 VSIXs
Performance: The coexistence shouldn't affect the performance and AutoUpdate taken care by the VSPackage extension should not create redundant service calls.
No.
The only real "performance problem" you can have is putting the C# and VB ones in the same assembly (note, not VSIX), which would mean when we have to load one we load the others.
From the perspective of MEF, we just get a list of exports back: we don't know which VSIXes they're from, and it's hard to figure out if even if we wanted to. So which VSIX you put stuff in doesn't matter at all: divide them up based upon what makes sense for your users.
Caveats of Roslyn and VSIX packaging:
As mentioned by Srivatsn
Extensions that refer to both Microsoft.CodeAnalysis.CSharp and Microsoft.CodeAnalysis.VisualBasic will
Load both the compilers even if we try to open a C# project, this is not ideal.
If we have to analyze the symbols ISymbolAnalyzer,where you are analyzing just the symbols and not the syntax nodes, then we should adopt a single language-agnostic analyzer. This means we don't have to refer any C#/VB dlls (Even Microsoft is thinking about implementing more language-agnostic analyzer). Include two export attributes - one for each language, these attributes tell VS to instantiate and call these analyzers when the respective language is contained in the solution.
Compilation as a process leaves the memory after the compilation is done, but since there is a compilation happening at almost every keystroke and if the analyzer refers to both c# and VB, it will bring both compilers into memory. Since there is a persistence characteristic, it could be a problem if there is a large project under the solution (This is my typical production scenario)
There is a confusion whether the compiler is loaded when the respective syntax method is invoked or on instantiation of the exported analyzer (which is again being filter through the MEF export attribute by mentioning the respective language use case) since he also mentioned that the if a method that refers to both kind of syntax node might make the JIT compile and load the dlls.
Any analyzers linked to menu command would be VS specific and if they are linked to the project then it will participate in the build as well, even outside of the VS through MSBuild
VSIX should be able to export multiple components for extending both of those extension points.
As mentioned by VSadov
Persistence of the syntax tree data-structure and the need to re-do analysis at every keystroke(delta-compilation: this is what Srivatsn's compilation means) made them design the red-green tree method which helps in the performance of the delta-compilation.
As mentioned by SLaks
MEF exports doesn't make any difference whether they are packaged in a single VSIX or not (but it should be noted that there is a performance issue related to combining both type analyzers into a single assembly which is an MEF export)
As mentioned by Kevin Pilch
Although it doesn't matter where these assemblies are packaged in unless they are separate in concern when it comes to language specific references.
Virtual memory will be reserved if the analyzer references both the C# and VB specific Roslyn assemblies and these compiler assemblies are large
The performance problems being Disk loading and JIT costs (I'm not sure how there is a JIT cost if there is no compilation and only reference in it), but since there is an address space reserved there could be an issue in VS (I'm not sure how that will be an issue.)
What Microsoft does, according to him, is to create three projects to deal with this (According to Srivatsn Microsoft is still trying for language-agnostic analyzers)
Shared (No language specific binaries in it)
C# specific (+ shared libraries)
VB Specific (+ shared libraries)
If no language specific binaries are referred and if the MEF exports are appropriately attributed with ContentType or LanguageName then the above issue can be solved
We can bundle additional assemblies into a single VSIX (by embedding the other project in it) and VS will load each independently
Final Implementation:
So Finally I came to a conclusion after discussion with my team as follows
A single VSIX implementation by embedding the following projects in it
Update plugin
Checks if update was present in the past 7 days
Then checks for the version number of the Plugin from server side via a JSON request
Then downloads the plugin from the server, stores the download date in VS settings for initial check
Disables the previous plugin
Uninstalls the previous plugin
Installs the new plugin
This functionality is triggered when
The VS loads
Manual menu command (which should override the download date check)
C# plugin
Implements and refers only rules for C#
VB Plugin
Implements and refers only rules for VB

How do I add a reference to an assembly that wasn't built with the Silverlight Runtime?

I am looking for a possible solution where I can add ShapeMap.dll as a reference,
but when I try to add the reference I get an error stating:
You can't add reference to ShapeMap.dll, as it was not build against the Silverlight runtime. Silverlight projects will only work with Silverlight Assemblies"
What do I do now?
While Silverlight code may look and smell like good old .NET-backed logic, the runtime for Silverlight is different from that supporting regular .NET applications.
It is useful to think of the Silverlight runtime as a subset of the .NET runtime: Silverlight is meant to run in a "sandbox" whereby many the unsafe features such as direct access to the file system are not allowed.
For this reason, one can only add Silverlight assemblies to a Silverlight project.
The error you're getting is therefore as said: the version of ShapeMap.dll you have wasn't build for Silverlight runtime.
There are two ways out of this situation:
find or build a Silverlight-backed version of the DLL
somehow refactor the Silverlight application so that it leverages the features of the DLL by way of WebServices (if that makes sense, for the name ShapeMap.dll indicates that this may deal with UI objects which are hard/impossible to deal with remotely)
To get a Silverlight-backed version of the DLL:
First choice: It may just be that you can get the binary of the Silverlight version of the assembly where you found the .NET version.
Second choice: it may be that you can get the the source code of the [.NET targeting] DLL.
If so you can try -and I stress "TRY"- to make a Silverlight assembly out of it. The problem may be that the source code uses .NET-only idioms/API calls and you'll then need to convert these; several just .NET-to-SL "gotchas" can easily be converted, others are absolute roadblocks (eg. direct access to the file system, registry etc.), although, it may be possible to merely comment-out the offending sections of the code, if, somehow the Silverlight was not going to use the underlying features of the DLL.
Now... for sake of full disclosure...
there are a few techniques which allow "fooling" Visual Studio so that .NET assembly be accepted within a SilverLight project. See for example "Reusing .NET assemblies in Silverlight". Beware, however, that while very insightful as to the nature of the .NET and Silverlight runtimes, and possibly useful in some cases, these techniques are undocumented and, more importantly, depending on the subset of .NET API used by the DLL, may merely allow to get over over the build-time blocking, to fall into various run-time errors (when/if the application makes calls into the DLL to methods which in turn invoke .NET-only methods of the runtime).
If you have access to the source files for that assembly (dll), create a new Silverlight Class Library project and add all the existing source files to your new project. Then attempt to build the project. Depending on the amount of dependencies you may succeed in building a silverlight compatible version of the assembly.
If you don't have the source code, then sorry you're out of luck.
Silverlight works in a "subset" of the .net framework, some stuff is organized differently and works not like a regular WPF application (like that everything needs to be async in order to keep the UI responsive). You can see it as a "protected" .net environment, and therefor you may not reference or use non-silverlight dll's.
Like the previous answer states, use the source code and copy paste it into a SL library project, compile, and use that.

The .NET equivalent of static libraries?

I'm building a tool in managed code (mostly C++/CLI) in two versions, a 'normal user' version and a 'pro' version.
The fact that the core code is identical between the two versions has caused me a little trouble as I want to package the resulting tool as a single assembly (DLL) and I don't want to have to include the .cpp files for the common code in the projects of the two versions of the tools. I'd rather have a project for the common code and a project for each version of the tool and have each version of the tools project depend on the common code and link it in as desired.
In unmanaged C++ I'd do this by placing the common code in a static library and linking both versions of the tool to it. I don't seem to be able to get this to work in C++/CLI. It seems that I'm forced to build the common code into a DLL assembly and that results in more DLL's than I'd like.
So, in summary, I can't work out how to build the common code in one project and link it with each of the final product projects to produce two single DLL assemblies that both include the common code.
I'm probably doing something wrong but I tried to work out how to do this using netmodules and whatever and I just couldn't get it to work. In the end the only way I got it working was to tell the linker to link the build products of the common code assembly rather than the results which works but is a bit of a hack IMHO.
Anyway, does anyone have any suggestions for how I SHOULD be solving this problem?
Edited: I guess I should have mentioned the fact that the assemblies generated are not 100% managed code, they contain a mix of managed and unmanaged code as is, probably, quite common with assemblies produced with C++/CLI...
If you are annoyed at all the DLLs, download ILMerge. I use this to bundle together multiple DLL's into an easy-to-use .EXE for my clients.
If I'm understanding this correctly, you have a solution which contains two projects. One project for the "normal" user and one project for the "pro" user. Visual Studio allows you to add a "link" to another file source from another project. If your "pro" version has the real core code file, and in your "normal" version you add existing -> find the file in the "pro" project, and click the down arrow by the Add button and select "Add as Link". Now you have single file that is literally the same between two projects.
As said, ILmerge is one way. Personally, if you're bundling some exe with a lot of DLLs, I favor Netz.
You could use modules. You can link them into an assembly using the assembly linker, al.exe.
That's the downside of the .Net compilation process, you can't have things like static libraries and the header files that hold them together, everything is held in one big dll file and the only way to share information is to either build a common dll and reference it from other assemblies or to duplicate the code in each dll (possibly by copying/linking .cs files between projects).
Note that the 2nd way will declare different types, even though they have the same name. This will bite you on the ass with stuff like remoting (or anything that requires casting to specific shared interfaces between processes).
Remotesoft Salamander will hook you up. It's basically a native compiler and linker.
When using mono (or cygwin is an option) mkbundle may also be a valid choice.

How can compilation of C# code be made to require a given language or compiler version?

How can a C# program detect it is being compiled under a version of C# that does not contain support for the language features used in that program?
The C# compiler will reject the program, and produce some error message, on encountering the features of the language it does not support. This does not address the issue, which is to state that the program is being compiled with too old a version of the C# compiler, or a C# compiler that does not support the required version of C#
Ideally, it would be as simple as
#if CS_VERSION < 3
#error CSharp 3 or later is required
#end
I don't believe you can do that with a C# file, but if you're using MSBuild then the project/solution tools version number can stop it from being built with an older version of MSBuild.
Can you give the exact context of this? One "human" solution rather than a technical one might be to try compiling the code with all the "old" versions, and create a document with: "If you get an error like this it probably means you're using the wrong version..."
Another option you might want to consider to make that even simpler is to have a single "required features" file. This would be unused by your main app, but ask users to compile that first. If it works, the rest of your build should work. If it doesn't, it's due to using the wrong version. That's likely to produce a smaller range of errors from different versions (in particular it doesn't have the problem that the compiler could list errors from different files in a random order).
According to this list of preprocessor directives, it doesn't seem possible. We usually can tell by using generics (detects 2.0), using auto properties (3.0) or dynamic (4.0)
Easy: The compiler will fail and give you an error if it can't compile the code.
There is no predefined symbol for this; you could create your own symbols and define them in your build script. Note that you can fix the language version at the project level:
Project properties -> Build -> Advanced -> Language Version:
ISO-1 is C# 1.2
ISO-2 is C# 2.0
(maps to the csc /langversion parameter)
But note that this doesn't cover everything - there are a few things that this will let through - particularly in the area of generic type inference. This is only an issue if you need to support old compilers; in which case... test with an old compiler.
For example:
int[] arr1 = { 1, 2, 3, 4, 5 };
string[] arr2 = Array.ConvertAll(arr1, delegate (int i) {return i.ToString();});
This works in .NET 3.5/ISO-2 (pseudo C# 2.0), but doesn't work in .NET 2.0 (proper C# 2.0).
Perhaps you can read the supportedRuntime element:
Then you can define the directive you want based on the supportedRuntime, using CSharpProjectConfigurationProperties3.DefineConstants.
You would create a macro in VS to use this.

Use VB.NET and C# in the same application?

I am developing a GUI based application in MS Visual Studio 2005, I just want to
know if it is possible to use both VB.NET and C# in the same project. Or can I include a module written in C# in my VB.NET project?
I have a class written in C# which I want to use in my VB.NET based project, so if I can include and call functions from that project than I won't have to write the class again in VB.NET.
So please help me as I am new to .NET programming.
I just want to know that is it possible to use both VB and C# in the same project.
No, not in the same project. On the other hand, you can use them in the same solution.
Or can i include a module written in C# in my VB.net project.
I propose that you create a solution containing two projects: one in C# which forms a library that you use from your VB project. This is straightforward, easy to maintain and easy to extend.
I've never done it myself, but I know you can compile the C# code into a dll and then load and reference the dll in your VB project.
From "Calling C# class in VB.net":
I think the C# code that you want to
use must be compiled as a DLL. Once
that is done, simple add a reference
to that project to your VB.Net
project, import the namespace you
need, and then you can use the C#
code.
Also see How To: Create and Use C# DLLs (from MSDN, for VS2005)
You also want to ensure that you C# code is CLS compliant. This means that it won't publicly expose any functionality which other .NET languages won't understand (for example unsigned ints - which don't exist in VB, or differing classes only by case - since VB is not case-sensitive). To do this you need to add an attribute so that the compiler will raise errors if you have broken any of the guidelines. This article shows you how to do this:
The CLSCompliantAttribute can be applied to assemblies, modules,
types, and members.
For marking an entire assembly as CLS compliant the following syntax
is used
using System;
[assembly:CLSCompliant(true)]
For marking a particular method as CLS compliant the following syntax
is used
[CLSCompliant(true)]
public void MyMethod()`
Put VB.NET and C# code in separate projects. (I am using both VB.NET and C# in my open source project, http://msquant.sourceforge.net/, and it works great).
You don't need to worry about DLLs, just reference the project (use tab "Project" in the "Add Reference" dialog box). E.g. if you need to use a function in the C# code/project add a reference in the VB.NET project to the C# project.
You can't use a C# file and VB file in the same project. You can, however, have VB and C# projects in the same solution and reference them.
In your code you can use:
Imports namespace
or
using namespace
Once the reference has been added to the appropriate project build the solution and you are good to go.
You can also create a VB.NET Library in a separate solution, compile it and import the DLL into the C# Project or vice versa.
You must also know that if you have a VB.NET project with a C# project in the same solution with one of them having a reference to the other, changes apply in the referencing project will just be available to the other after rebuilding the solution. It's like having binary reference, but with the capability to change code on the same solution.
Personally, I don't like this, but I'm always in the situation where I modify the code in the referencing project and don't know why my changes are not in the code where I use it and I figure it out, oohhhh, I must rebuild.
For temporary help, it could be acceptable but not for programming every day.
If you were only planning on using the module in Visual Basic projects, then you should consider just converting the code to Visual Basic. If you need to use the module in both C# and VB.NET programs I would use one of the solutions posted above
You might try something like *Convert C# to VB.NET. It converts C# to VB.NET code. I use this page exclusively when I have to convert something I find on the net that was written in C#.

Categories

Resources