I've written a library of expression-tree-related test objects (for the types in System.Linq.Expressions), which I use in tests for ExpressionTreeToString.
The library is in two .NET Standard class library projects within the solution:
ExpressionTreeTestObjects -- expressions generated via the C# compiler and by calling the expression tree factory methods
ExpressionTreeTestObjects.VB -- expressions generated by the VB.NET compiler
ExpressionTreeTestObjects also exposes the main entry point for getting the list of objects (via reflection over the assemblies in the current domain).
I want to publish both DLLs as a single NuGet package.
Where should I put the NuGet package information?
The obvious choice (to my mind) is in ExpressionTreeTestObjects. But how can there be a reference there to ExpressionTreeTestObjects.VB, when ExpressionTreeTestObjects.VB also depends on ExpressionTreeTestObjects? Isn't this a cyclical build dependency?
I suppose an alternative would be to separate code which generates the expression tree objects, from the main entry point code; and put the entry code in a third project (ExpressionTreeTestObjects.Loader) which would reference both original projects. The package information would then go on that third project.
But adding a separate project feels like it should be unnecessary.
I've included the package information in the ExpressionTreeTestObjects.VB project, as can be seen here.
Related
I'm building package for my project in C#, and I want to reuse it across different projects.
Some Utility methods/classes in my package are dependent on another package (say RX .Net). But I know that I would use this package in projects without RX .Net installed.
For example I have class EmailSender, which has callback - style methods (void .Send(attrs, Action clb)) as well as RX based methods (IObservable .SendAsObservable(attrs)).
Could I do something like
#IF PACKAGE EXISTS RX.NET
# ENDIF
So parts of my code will be ignored if package does not exist?
Which is the best way to accomplish something like this without building 2 separate packages with duplicate class names etc.
Investigate using a fake assembly in the references of your project: adding a fake reference can resolve missing dlls: Code generation, compilation, and naming conventions in Microsoft Fakes
Example of faking individual methods:
Using Microsoft Fakes with mscorlib.dll
I have two projects:
ProjectMain (class library)
LibraryProject (class library)
ProjectMain is a class library that should only be compiled as a singular library, no referenced libraries. I require a static class reference from LibraryProject BUT I don't want the LibraryProject assembly to be compiled together with the ProjectMain assembly.
I've tried 'link references' in visual studio but this is no solution as the library assembly is always compiled with the main assembly.
There are clear standard solutions to this issue but I am severely limited by the existing implementation requirements. Only one DLL can be compiled without any of the dependent assemblies being in the execution folder, GAC, private path, reflection etc.
The exact limitations are as follows:
Assembly executed in a sandbox from a third party provider, it only supports adding a single assembly with no direct references/reflection etc (it's horrible but my hands are tied)
We would like to handle the code organisation as best possible which means following standard best practices, unfortunately, due to the above limitation that's proving difficult.
What I would like to know is if there is a way to reference a class within another project without also compiling/using that referenced classes assembly. Possibly a method where the compiler 'embeds' the referenced class at compile time.
If your sandbox does not allow loading other dlls in AppDomain, load it yourself by embedding it. You can use Costura.Fody for this purpose, it is easy to use/install, just reference it from nuget.
Of course, embedding it in every scenario is madness and often comes with completely obscure bugs, which often solvable only by enabling traces in regedit.
So, in your case I would create two projects:
MyDll.csproj //it is my original project, with perfect code design and etc. Lovely.
MyDll.Sandbox.csproj //this one is the same as MyDll.csproj, except it is compiled with additional Costura.Fody reference, into single dll (every reference is put inside)
This way you just need to maintenance that MyDll and MyDll.Sandbox files are the same.
I have a project which needs to indirectly use three different versions of a third-party library. These versions are incompatible with each other, so I can't use a binding redirect - it has to be the exact .dll file. (The libraries are Spire.Doc, Spire.XLS & Spire.PDF; the Spire.PDF DLL is referenced by all three)
I have separated the three components into individual wrapper projects, and created classes which wrap direct references to anything in the libraries. However, this doesn't solve my issue: the 'consuming' project still has to copy all of the libraries to the bin folder in order to run. The build process doesn't know which version to copy, and so just copies the latest one. This gives me runtime exceptions due to the wrong DLL being present.
What I've considered/tried:
Adding a binding redirect to a specific version (runtime exception because the exact version of the library is not found)
Using a post-build step to merge the wrapper projects (again a runtime exception complaining about the absence of the library DLL)
Creating separate console applications for each part of the application, then invoking them in a separate - this is a complicated last resort that I'd really rather not do!
I have read that extern alias might be able to help - but as far as I can tell, you can only distinguish between assemblies with different names. The Spire.PDF library has the same name in each project (and the same signed public token).
How can I use these three separate versions of the library independently in the same solution?
Edit:
This issue is slightly different to the suggested duplicate because I don't have the ability to change any code in the dependent libraries. Spire.Doc relies on a different version of Spire.PDF to Spire.XLS
In your consuming project (Project A), create a common interface (ISpiroPdfAlex) that encompasses all the functionality that the 3 versions of your external assembly provides (and you use). You cannot reference anything in Project A from these wrappers in any way, otherwise you'd create a dependency, which is what you're trying to avoid.
Have all 3 wrapper projects import Project A and implement ISpiroPdfAlex. This will give you the ability to call each of the 3 different versions through the same API.
After this, create a subfolder under Project A for each of the versions (so 3 subfolders total) - since Project A has no reference to any of the external assemblies, it cannot load them by itself - you'll have to manually load them when you need the right version. Since your external DLLs may have dependencies with the same name, they cannot all be in the same folder (as you wrote), this is why you need the subfolders.
At run-time when you need one of these versions, you can call Assembly.LoadFile to load a specific version of your assembly from the specified folder and then you can either use Activator.CreateInstance or dependency injection to create an instance of a class that implements your interface. Once you have the instance, you're free to call any of the functions and you'll get version-dependent behavior.
Edit:
OP mentioned in a comment that it's not his code that has the dependency on different versions of the PDF library but the other 3rd-party Spire libraries that his code depends on.
In this case, the 3rd-party code cannot be modified to support dynamic loading of assemblies and they already have a binary dependency. It's not possible to load different versions of the "same" assembly into the same process, especially that you mentioned that these versions are not even backward-compatible with each other.
The only solution I can think of in this situation is to break out all dependent functionality into separate console applications (one for each different version) and call those separate .exe-s through the command-line.
To pass information, you can either pass data directly on the command-line or through stdin. Alternatively, you can just pass the name of a temporary file that has all data necessary to do some processing. To get return data back from the console process, you can either read its stdout or use the same / different file.
This way your main process never loads any of these assemblies and has no dependency on them - each console application has a dependency on just one version so there's no collision.
Let's say you have two projects:
Main.csproj
Main.Test.csproj
And Main has an attribute
[assembly:InternalsVisibleTo("Main.Test")]
Now we want to reference a NuGet package that ships its content as source code such as MoreLinq (https://code.google.com/p/morelinq/) in both projects.
The problem is that there are now two copies of the source visible to the Main.Test project and therefore the compiler spews an Ambiguous reference error.
Is there any way to avoid this without modifying the source code that the package drops into each project?
P.S. Please don't use arguments such as 'don't use InternalsVisibleTo because...'. I can read those points elsewhere.
The extension methods from morelinq will be public so if you have them in main.csproj, you won't need them in main.test.csproj but they'll still be accessible within main.test.csproj.
A lot of my projects contain the Castle/NHibernate/Rhino-Tools stack. What's confusing about this is that Castle depends on some NHibernate libraries, NHibernate depends on some Castle libraries, and Rhino-Tools depends on both.
I've built all three projects on my machine, but I feel that copying the NHibernate/Castle libraries is a bit redundant since I built Rhino-Tools using the resulting libraries from my NHibernate and Castle builds.
Right now, I include all projects in seperate folders in my /thirdparty/libs folder in my project tree. Should I simply just have /thirdparty/libs/rhino-tools in my project and use the Castle/NHibernate libs from there? That would seem to make logical sense in not duplicating files, but I also like having each project in it's own distinct folder.
What are your views on this?
This is one of the problems that we're trying to tackle in the Refix open source project on CodePlex.
The idea is that Refix will parse all the projects in your solution, and before your project compiles, copy the necessary binaries from a single local repository on your machine into a folder within the solution tree and point the projects at them. This way, there's no need to commit the binaries. Your local Refix repository will pull binaries from a remote one (we're setting one up at repo.refixcentral.com), and you can set up an intermediate one for your team/department/company that can hold any additional software not held centrally.
It will also try to resolve conflicting version numbers - Visual Studio can be too forgiving of mismatched component version numbers, leading to solutions that compile but fall over at run time when they fail to load a dependency because two different versions would be needed.
So to answer the question "how do you package external libraries in your .Net projects", our vision is that you don't - you just include a Refix step in your build script, and let it worry about it for you.
I use a folder for each, which seems to be the convention.
Does it really make a difference if you're copying them?
What if you want to switch one out? Let's say you go with a new O/R mapper. It will be much easier to just delete the NHibernate folder than to selectively delete DLLs in your Rhino-Tools folder.
Take this to it's logical conclusion and you won't have any folder organization in your lib folder since everything uses log4net :)
Add additional probing paths to your app.config files to locate the dependency dlls. This way your can get away with having just one copy of everything you want. Though there are some quirks to using this feature (you must create the folder structure in a certain way). Look here for more details on the tag.
I will definetly recommend having a thirdparty or vendor folder in each of your project trees. If you find it annoying to have 32 copies of the rhino-tools package, you can have a single copy of it in your code repository, and do external references to it in your project tree.
Lets say you are using SVN, you can make a repository called "thirdparty libs" and in this have versioned copies of the libs. You then make an external property on your "thirdparty"-folder in your project tree which then in turn automaticly will do a check out of your centralized thirdparty libs. This way you for instance only have to update in one place if a security or a bugfix comes out, but each project is still in command of choosing which thirdparty libs, and which versions to use.
About the deps internally in thirdparty libs, i wouldn't mind those. The first time you compile your project, and some of the libs arent copied to your bin-folder because of implicit dependencies you can add an external attribute into your bin-folder, which will then automaticly check out the missing libs. That way you still only have to update your thirdparty libs in one place.