Using Code Contracts, why does ccrewrite require access to every runtime dependency? - c#

I'm trying to use Code Contracts and I'm running into a problem that is blocking me. With Contract Reference Assembly set to Build, ccrewrite is erroring while trying to access assemblies that are referenced indirectly by assemblies that are referenced directly. These indirect assemblies are not needed to build the solution, so I'm wondering why they're required by Code Contracts? Also, is there a way to work around this problem without having to provide all runtime dependencies as part of the build?

I assume ccrewrite is trying to walk the dependency chain to analyze it for pre/postconditions, etc.. If the assemblies are referenced by assemblies which you in turn reference, then they would be required for your program to run, so ccrewrite is just performing normal analysis before you actually run the program.
That's based on using JML; I've only just started looking at the .NET Code Contracts myself. But I believe both tools operate on roughly the same principles.

The rewriter looks into method bodies of referenced assemblies in order to extract contracts (the C# compiler never does that). As a result, the rewriter often chases more dependencies than C# which is the problem you ran into.
There are two ways to address this.
add extra paths to directories where the desired libraries can be found (in the contract library paths options). This it the preferred method
As a last resort, you can add the option -ignoreMetadataErrors to the runtime contract options. Note that this is dangerous. In the case that the rewriter truly needs some aspect of the referenced code in order to create proper IL, you might end up with incorrect IL. To guard against this, use peverify on the resulting bits.
Hope this helps.

Related

When to create and distribute "reference assemblies"?

C# 7.1 introduced a few new command line parameters to help create "reference assemblies". By documentation it outputs an assembly which:
have their method bodies replaced with a single throw null body, but include all members except anonymous types.
I've found an interesting note that it is more stable on changes:
That means it changes less often than the full assembly--many common development activities don't change the interface, only the implementation. That means that incremental builds can be much faster- ...
and that it is probably necessary for roslyn itself ..
We will be introducing a second concept, which is "reference assemblies" (also called skeleton assemblies). [---] They will be used for build scenarios.
.. whatever those "build scenarios" are for Roslyn.
I understand that for ordinary .NET assembly users, such assembly is probably smaller and slightly faster to load for reflection. Ok, but:
usually you also care about execution and the implementation assembly already contains all the data from reference assembly,
quite often you don't care about that minor performance difference on loading,
and most importantly - usually you don't have that stripped-down reference assembly available (distributed) at all.
It's usefulness seems rather niche.
So, I wonder about the general assembly producer side of things - when should one consider explicitly using those new compiler flags to create a reference assembly? Does it have a any practical use outside Roslyn itself at all?
The motivation for this feature is indeed build scenarios, but they're not specific to Roslyn; they're your build scenarios, too.
When you build your project, the build engine (MSBuild) needs to decide whether each output of the build is up to date with respect to its inputs. For example, if you don't change anything and just run build twice in a row, the second time doesn't need to invoke the C# compiler: the assembly was already correct.
Reference assemblies allow skipping the compile step for assemblies in more scenarios, so your builds can be faster. I think an example would help illustrate.
Suppose you have a solution containing B.exe that depends on A.dll.
The compiler command line for B would look something like
csc.exe /out:B.exe /r:..\A\bin\A.dll Program.cs
And its inputs would be
The source for B (Program.cs)
The assembly for A.
If you change the source of A and build your solution, the compiler must run for A, producing a new A.dll. Then, since A.dll is an input to the compilation of B, B has to be recompiled, too.
Using a reference assembly for A changes this slightly
csc.exe /out:B.exe /r:..\A\bin\ref\A.dll Program.cs
The input for A is now its reference assembly, rather than its implementation/normal assembly.
Since the reference assembly is smaller than the full assembly, that has a minor effect on build time all by itself. But that's not enough to justify this feature. What's important is that the compiler only cares about the public API surface of the passed-in references. If an internal implementation detail of the assembly has changed, assemblies that reference it do not need to be recompiled to pick up the new behavior. As #Hans Passant mentions in comments, this is how the .NET Framework itself can deliver compatible performance improvements and bug fixes on unchanged user code.
The benefit of the reference assemblies feature comes from the MSBuild work done to use them. Suppose you change an internal implementation detail in A but don't change its public interface. On the next build,
The compiler must run for A, because source files for A changed.
The compiler emits both A.dll (with the changed implementation) and ref\A.dll, which is identical to the previous reference assembly.
Since ref\A.dll is identical to the previous output, it does not get copied to A's output folder.
When it is time for B's compiler to run, it sees that none of its inputs have changed--neither B's own code, nor A's reference assembly, so the compiler doesn't have to run.
B then copies the updated A.dll to its output and is ready to run with the new behavior.
The effect of skipping downstream compilation can compound as you go along in a large solution--changing a comment in {ProjectName}.Utilities.dll no longer requires building everything!
Many changes involve changing both the public API surface and the internal implementation, so this change doesn't speed up all builds, but it does speed up many builds.

Is there an easy way to modify a decompiled file without having to deal with its dependencies?

I managed to decompile a c# file (using dotpeek) and I want to edit a couple of simple things (using visual studio).
The problem is this file has many dll dependencies even though the edits are necessary only on the main exe.
Obviously if you try to build an exe on vs without having the references and dependencies in place the compiler will complain. Are there any solutions to this?
You cannot build without the dependencies; however, there is no need to decompile the dependencies. Just add the DLLs themselves as reference to the project.
This is always fine if the decompiled assembly depends on other DLLs; however, if the other DLLs depend on the decompiled assembly, this will only work if the assemblies are not signed, i.e. if they are not using strong names. The purpose of signing is precisely to disallow such hacks.
No, you can't build without the dependencies because the compiler has to check that types match and have the indicated members etc.

Reference has not compile-time usages

I've been watching over the architecture view of our solution created by ReSharper, when I noticed some of the project references has no compile-time usages, does that mean I can change assemblies at runtime?
In simple terms, no compile-time usage means that your code will compile even if you remove the reference. You cannot directly derive anything regarding runtime from this statement. It might even be that your application runs perfectly fine if you just remove this reference. It might also be that your reference is somewhat obfuscated and the compiler doesn't know it. This could be because the reference is implementing interfaces that you compile against or you are looking for it manually at runtime (see Florians answer). You could probably also hide it with reflection if you really wanted to. But that would also need to load the assembly manually at runtime.
At compile-time, the compiler will link the new binaries to the corresponding code in the referenced assemblies. This will allow automatically loading the assembly at runtime. It will also copy const values to your assembly.
You can definitely change the referenced assembly between compile- and runtime, although you should tread very carefully. If method signatures changed, compile-time references will break.
At runtime, referenced assemblies will be loaded once you try to interact with them. Once an assembly is loaded, it cannot be unloaded directly. You can only unload AppDomains. So if you want to change assemblies at runtime, look into AppDomains.
So what could be an intended use of those non-compile-time references? The most common architecture that uses this was mentioned by Florian in the other answer: Plugins. Also other dependencies where you want to separate your code from the actual implementation via interfaces. Your project references without compile-time dependencies are then only used to deliver the implementation to the actual application. Otherwise you would need to add this to your delivery and debugging process, which can be a pain depending on your project.

Dynamically change namespace and assembly name

Basically, I developped a small library with some common fonctionnalities that I use in all my projects. For some political reasons, I cannot choose a generic name for that library (including namespace and assembly name). Usually, it must include the name of the enterprise, something like this for the namespace: Enterprise.ProjectName.XXX.YYY.
For the moment, I'm doing a copy of my library, then I'm renaming the namespaces manually with Visual Studio, and finally I'm recompiling the whole thing.
So my question is the following: Is it possible to create a small program that takes an assembly as input, rename all namespaces from MyLibrary.XXX.YYY to Enterprise.ProjectName.XXX.YYY as well as the assembly name?
What are the steps to follow?
[Edit]
Generating the assembly automatically seems to much work. I will use resharper and/or CTRL+ALT+F like I did so far. Thanks for the answers...
You could use Mono's Cecil project to disassemble the assembly, inspect each type, rename or recreate the type with a new namespace, and generate the resulting assembly.
That being said, it might be simpler to use a tool like Resharper which allows you to rename namespaces correctly within the code base.
Some options:
If you are copying the entire source code for your library into your new project, you can use a refactoring tool like Resharper to "Adjust Namespaces". This is a pretty quick and safe refactoring.
If you just need to avoid shipping the internally named assembly, you may be able to use ILMerge to 'hide' the internal assembly during a post-build step. This is viable if it's just a perception issue for the final assembly names in the binary output directory.
Deal with the issue at the political level by describing your internal library as being no different from any other third-party dependency. Then the naming is no longer a problem. This may solve other problems if you're shipping the source code of this library to multiple clients, as it clarifies that you are not giving full ownership of your 'shared' code to each client. Otherwise they could potentially argue that you are not allowed to use that 'shared' code in projects for other clients, since it is clearly owned by them, having their enterprise name in the namespace.

Using C# preprocessor to add reference

I have a large application that I can build through the command line. I want to specify a flag that enables me to compile it into either one of two modes, Actual or Simulated.
So the main issue is, how can I use the preprocessor to programmatically add a reference?
For example:
#if SIMULATED
include SimulatedFiles;
myFactory = new SimulatedFiles.simFactory();
#else
myFactory = new realFactory();
#endif
I don't want any simulated files to compiled into my "actual" application. Since there is no "include" directive in C#, I am stuck on how to accomplish this.
You cannot do this via a C# preprocessor statement because the language doesn't support the notion of references via preprocessor macros.
What you can do is use a msbuild file and alter the set of references added based on msbuild parameters.
nant/msbuild and dependency injection tool with xml configuration?
In C#, there is no real preprocessor, as you can read on the C# Preprocessor's documentation.
From the documentation (emphasis mine):
While the compiler does not have a separate preprocessor, the directives described in this section are processed as if there was one; these directives are used to aid in conditional compilation. Unlike C and C++ directives, you cannot use these directives to create macros.
Are the include files your own source code, or third-party assembly dlls?
If they are your own sources, then you can easily use conditional compilation to remove the "simulated" code from your release build, exactly as you have done in your example (just replace 'include' with 'using'). This is common practice with debugging classes for example.
If you don't "control" the source code for the includes, then you can still add a project reference, but if you conditionally compile all the code that uses the assembly, your applicaton won't ever attempt to access the assembly, so it doesn't need to be be present when the code is running.
(Another possiblity that seems less useful for you is to write a "dummy" version of the referenced assembly that you ship in place of the "real" one, or a proxy that calls the real third-party dll in simulated builds only. If it supplies the public classes and methods that you call, you can ship the dummy instead of the simulated assembly to your customers)

Categories

Resources