.NET: with respect to AssemblyVersion, what defines binary compatibility? - c#

What changes to a strong-named assembly necessitate a change in AssemblyVersionAttribute? Clearly, changing the public api in a way that could require a client to have to make a code change requires an increase in AssemblyVersion. But what about changes to the public API that don't require code changes in the client? For instance:
the addition of a public class or interface?
the addition of a public member to a public class or interface? (EDIT: drscroogemcduck correctly points out below that adding a member to an interface would hose all implementors. Silly me.)
an increase of visibility of a class member?
There's got to be definitive documentation of this somewhere on MSDN (or, knowing MS, on some MSSE's personal blog). But I simply cannot find it. Please help!

In response to Martijn's bounty:
The best reference on binary compatibility is on the community Wiki.
A definite guide to API-breaking changes in .NET

It's pretty easy... as long as Types remain unchanged (in their public or protected layout) and method signatures are not changed (adding methods or types is fine), the JIT should be able to link the DLL just fine.
That said, I think that even if it does work you should not do this. Make a new version and use a policy to map the old version to the new one, if required. Otherwise you drive yourself straight back to DLL hell... and I'm pretty sure you don't want that.

adding methods to an interface shouldn't be fine because old providers won't implement the new methods.

Microsoft adds new methods/classes in .NET libraries in service pack releases without changing AssemblyVersion (still 2.0.0.0 / 3.0.0.0). Microsoft only changes the AssemblyFileVersion.
For example, In .NET 2.0 SP1, DateTimeOffset struct was added.
Should this practice be recommended to us because Microsoft do this?
It is confusing.

Related

Excluding classes from Nuget package

Update for clarification:
I have a project which is exposed as Nuget package. I need it to be public to my solution assemblies but private to who ever will consume my package. Is there a way to accomplish that?
Original question:
A project I'm working on is currently using 2 entities projects and it's written over .Net Standard 2.0 framework:
Contract.csproj
Contract.Internal.csproj
The first is configured to be exposed for consumers using a private Nuget server, while the second is for internal use of my solution projects.
The thing is that both has pretty much the same classes except few that are for my solution internal use only.
Is there a way to merge them to a single project and configure some classes to be exposed in the NuGet package while others are not?
I read on the ExcludeAssets/IncludeAssets tags that can be added to the csproj PackageReference, but the docs and all the examples I saw are referring dependencies and their versions and not the project classes.
Also, if you have other solution, you work with your projects some other way on this one (Or even think that I find myself with that scenario is wrong) I'll be more than happy if you share you thoughts on this.
If you want to expose certain classes from your project while keeping other classes internal, you can use C# access modifiers.
For example, a class prefixed with internal will be only visible inside your project:
internal class Foo { }
A class prefixed with public will be accessible for others:
public class Bar { }
I think Wouter's answer should help resolve your problem. But I want to highlight another approach to a similar problem that may help you or other folks in the future.
Since there is an interface/functionality in Contract.Internal.csproj that is internal but needed in Contract.csproj, as a possible solution, instead of making its interface public, you can restrict it with internal modifier. And in order to access that internal interface in Contract.csproj, you can use this answer.
What you'll have to do, is to grant access of the internals visibility to Contract.csproj by modifying the AssemblyInfo.cs file of the Contract.Internal.csproj the following way:
[assembly: InternalsVisibleTo("Contract.Internal")]
A single package is the wrong approach here because it violates the principle of separation of concerns. Instead, you should have MyPackage that has all the public code and is intended to be consumed by anyone, then for your own internal use have MyPackage.Private that references MyPackage. Your users reference MyPackage, you reference MyPackage.Private, and everything is simple.

Overriding method in DLL using reflection

I am not even sure if this is possible so apologies if not. I have googled quite extensively and not found what I am looking for.
Basically we have an application produced by a third party, which, to be perfectly blunt is rubbish. We have a particular issue and have managed to trace the problem using ILSpy to a method within a DLL. Obviously we don't have (nor are able to get) the source code and the company in question is unwilling to fix the problem in any reasonable timescales.
So, we've investigated various avenues of investigation and come up with nothing. I've been looking into seeing whether this can be done using reflection and this is pretty much the last hope we have of getting this to work. In a nutshell, what I would like to do is the following:
Create a simple class library with the same name as the existing DLL
Use reflection to import the methods from the existing DLL
Somehow override the method in question with my own, correct code
Rebuild the code, so I have a new DLL, containing 99% of the functionality of the existing DLL but with my override code providing the correct functionality.
I have found, during my investigations TypeBuilder.DefineMethodOverride and also a page from StackOverflow, which seems similar but not quite what I am looking for.
http://msdn.microsoft.com/en-us/library/system.reflection.emit.typebuilder.definemethodoverride.aspx
Is there a way to "override" a method with reflection?
Any advice appreciated!
Andrew
Edit
The other possible idea I has was to produce a partial class containing the override function, but that didn't seem feasible either.
You can override the method only if it is virtual, and it doesn't matter whether you do it through reflection or statically. I would suggest using a decompiler (there are a lot of free ones available) and fixing the code in MSIL. Then you can generate a new assembly from the MSIL.
I think your first idea is good.
If the third party class isn't sealed, you can derive from it, and add your own method, with a different name, to correct the behavior that is wrong.
If you need it to be in 1 dll, you can use IlMerge.
If your third party class is sealed you can just have an instance of this third party class in your new class and call the methods when needed.
But you'll have to check that the method you want to "override" isn't called inside that library, because if it is this solution won't work...
It's not very clean, but it can be a temporary solution during the time the company that edits the library fixes the problem.
And when it's fixed you'd just have to rename the method you use, so it won't be time consuming.
From what you have described I would recommend modifying the original assembly. The process is essentially
Decompile the assembly into MSIL, C# or whatever language you so choose
Modify the decompiled assembly to include your changes
Recompile the assembly using the modified source
From what I can see Reflexil allows you to do just that, although it may require that you buy Resharper (I've not tried it myself)
Alternatively you can use ILDasm to decompile the entire assembly to a single file, modify the file and then recompile it using ILAsm
I know I'm coming in a bit late on this, but I'd agree with Charleh; if you've got a class that's not behaving well and isn't conducive to substitution, but at least declares its methods as virtual, then you're in luck. The following uses references to Castle.Core and Patterns:
var interceptor = new DelegateInterceptor(proceed: call =>
{
if(ShouldCallProceed(call)) call.Proceed();
else AlternativeLogic();
});
var generator = new ProxyGenerator();
var proxy = generator.CreateClassProxy<UncooperativeType>(interceptor);
proxy.RubbishMethod();
I've also taken the liberty of providing a running sample of this in LinqPad. It shows the difference between methods that allow interception (virtual ones) and ones that don't. It also shows a useful way of trapping exceptions without all the code using Try.Do from Patterns.

In C#, how to restrict who can call a method at compile time

In C#, is it possible to restrict who can call a method at compile time?
I've looked into directives, but that didn't work since I can't assign values to symbols.
#define WHO VisualStudioUser.Current // does not work
I also looked into Code Access Security (CAS) but that's runtime enforcement, not compile time.
The requirement is to restrict access to a method at compile time for specific developers given the method exists in a pre-compiled assembly.
here's more details...
I'm building a framework or a series or assemblies for a team of developers. Because of our software license restrictions, I can only allow a few developers to write code to make a call to some restricted methods. The developers will not have access to the source code of the framework but they'll have access to the compiled framework assemblies.
The quick answer will be: No this isn't possible, and if you need to do it, you're Doing It Wrong.
How would this even work? Does it depend who who's running the code or who wrote it?
Edit There's kind of a way using InternalsVisibleTo and restricting accessing in source control to the assemblies that InternalsVisibleTo is specified for. See Jordão's answer
The requirement is to restrict access to a method at compile time for specific developers given the method exists in a pre-compiled assembly.
One way is to mark the method private or internal, it won't be callable by anyone outside the assembly. UPDATE: Also take a look at the InternalsVisibleTo attribute, which is used to define which assemblies can "see" internals of your assembly.
Another way is to divide the code you want to distribute from the code you don't want people to call into separate assemblies. Maybe you just share an assembly mostly of interfaces with your users, that they them compile against; and you have a separate assembly with implementations that they shouldn't reference directly. Your internal team would have access to the implementation assembly. This is just a common form of dependency management, the dependency inversion principle.
Draft:
Compile the restricted code into (obfuscated) DLLs: TypeA.dll, TypeB.dll etc.
Define an interface for each type, and compile them into separate DLLs: ITypeA.dll, ITypeB.dll etc.
Create a "guard assembly", and embed all restricted assemblies into it: Guard.dll. This has a ResolveEventHandler, and methods to instantiate different types defined in the embedded restricted DLLs. Instances are returned through their interface.
Developers get the interface DLLs and the Guard.dll. Each developer can get a Guard.dll with special authentication tokens in it. For example, a Guard.dll can be bound to PC, an IP address, a GUID issued to the developer, anything.
The developer can instantiate those types for which she has the proper authentication code, and uses the object instance through an interface.
Sorry this is a bit fuzzy, because it was more than a year ago when I used these techniques. I hope the main idea is clear.
Can you try using Extensible C# developed by ResolveCorp, some of the links for study and implementation are:
http://zef.me/782/extensible-c
http://www.codeproject.com/KB/architecture/DbCwithXCSharp.aspx
http://weblogs.asp.net/nunitaddin/archive/2003/02/14/2412.aspx
http://www.devx.com/dotnet/Article/11579/0/page/5

I want to modify an opensource wpf library, but update it as the donor library improves: how?

I'm intending to extend & alter an opensource library (LIB_A), which is itself composed of other libraries which have been modified for it's release.
My modifications are probably to be made to all of the libraries.
What is the best way to make subsequent importing of LIB_A into my library as painless as possible when new features are added/bugs are squished, without creating integration issues?
I was thinking of having my library sublass the classes I want to change, and override methods I want to change, but can't figure out if this is possible. The reasoning here is that I might only modify two methods in each class, so that when LIB_A bugs are fixed, if they're not in my modified methods - there is no collision, and I take advantage of the updates for free. If they are in the same method, there's no way around that, which I accept.
If I just copy the whole LIB_A, then I'll have to laboriously go through every file with a diff to see what has been changed, and then incorporate the updates. There must be an established way of doing this?
Is a source repository (local or otherwise) with it's associated check-in and diff behaviour the accepted method?
Thanks
EDIT: This SO question is asking exactly the same thing..
Well, you said it. If you can do it by subclassing, then by all means this is the simplest method.
The problem is that you not always can do it just via subclassing -- e.g. when you need to change a sealed or private method, change other non-virtual methods or properties etc. In this case, there is nothing you can do except to either (1) copy the code and create your own version, (2) modify the code such that those methods/properties are virtual and public -- but make sure it doesn't break anything elsewhere.
Even if you can subclass it, and the new version of the library does not touch the few methods that you overrode, you still have to test your changes fully agian, because your new code may depend on certain implementation details that the new version changed. Of course, the vendor of the library will have modified those few methods for the new version, but your version won't change. So the best way is to do a diff of the vendor's new version of your overridden methods with the old version to detect whether you need to change something in your own version as well.

If I add a public method to a C# class, do I need to recompile other assemblies using that type?

Question in the title.
I'd like to avoid recompiling since the source code I'm modifying is third party and I'd like to use the original binaries where possible, and replace only the assembly which contains the class I modified. But I'm not sure if this is a safe thing to do. In C++ for example this is definitely a bad idea.
No.
The assemblies that reference your library refer to methods and types using (some form of) name, so as long as you don't change the names of public types and methods (used by other assemblies), you don't need to recompile any of the assemblies - they will work with the updated version of the library.
In most cases Tomas answer is correct, but there are some cases where it is not true:
When using strong naming (signing) change of a single character leads to a new signature, thous leading to a new strong name.
Setting in your project references for your assembly the property Specific Version to true and changing the version number manually or automatically in AssemblyInfo.cs
No. All other assemblies will automatically work with the newly updated library.

Categories