I have created a DLL that contains the reference to Microsoft.Azure.Devices (and some other references).
I'd like to be able to just use this DLL in other projects without the need to reference Microsoft.Azure.Devices each time. Is it possible?
Currently, in order to use any function of Microsoft.Azure.Devices I have to reference it in my new project, which isn't a good solution I think - I'd like my DLL to be a "complete" reference - I just want to use the abstraction layer that I created without caring what is inside (what references are used).
That sounds like you want to use some kind of DLL weaving. That will merge all external referenced assemblies and your assembly into a new one.
There are multiple frameworks to achieve this. I personally have used these two:
IL Merge
Costura Fody
From a usage point of view fody was very easy to use. You basically reference it using Nuget (see https://www.nuget.org/packages/Costura.Fody/) That's pretty much it. It will pack all your references into one assembly.
You can find more information on the Git page https://github.com/Fody/Costura
The only limitation of this approach is that you can not use that with signed assemblies I think.
Due to an architecture requirement, I would have to have all the 3rd party dependencies centralized in a single project. Then, the remaining projects in the solution would have this project referenced as a dependency to inheriting all of these dependencies in order to avoid having them duplicated along the solution.
I'm wondering if that's possible even if I have to make some tricky adjustments to make it work.
Any suggestion will be much appreciated.
Thanks in advance!
If you reference a project, you are not necessarily referencing it's dependencies.
So, say I have Project A that references 3rdPartyLib.dll. when I reference ProjectA.dll, I'm not referencing 3rdPartyLib.dll.
One way to do it would be to write all of the logic that uses 3rdPartylib.dll in Project A, and essentially use it as an abstraction layer. Then reference projectA.dll and call that logic, and the calling assembly would have no knowledge of 3rdPartyLib.dll
I may not be asking this question correctly as I haven't been able to find a reference here or on Google. I need to modify a class that is in one of my reference DLL's. Will VS look at the reference DLL first or the local file first ? It seems to look at the reference DLL first. Is there a way to tell VS which to look at first ?
Thanks
Clarification - I have a class definition in the reference DLL and also in a local project file. The local project file is the class definition that I need the program to use.
Using an alias on your references, you can specify which of two similarly named classes you are referring to in your code.
This is explained by Jon Skeet here:
What use is the Aliases property of assembly references in Visual Studio 8
Limitations
This will only help you, if you instanciate that class yourself. It is not possible to let a foreign assembly create instances of your own class if there is no dedicated mechanism (i.e. API) for doing so.
Your question is quite vague, but if you use the Fusion Log Viewer FusLogVw.exe (just search for it on your computer) you can see what dlls are loaded and which paths were used to look for it.
This depends on how you setup your reference to the project in question. Visual Studio has 2 concepts of references.
Project to Project
Project to DLL
For the sake of this discussion lets call the main project A and the referenced project B (the class to change is located in B)
If there is a project to project reference from A to B then the build is always against the latest source code. Hence if you change the class definition A will always build against the changed class.
If there is a project to DLL reference from A to B then things are a bit murkier. There are so many possibilities here that it is hard to speculate intelligently what will happen. It may get the updated class, it may not, it may after a second rebuild.
In general though if you have 2 projects in the same solution and one references the other you should always use a project to project reference. The easiest way to guarantee this is to delete the reference, right click select add reference and go through the project route instead of "Browse".
I've searched for an answer on google using:
"The type 'Microsoft.SqlServer.Management.Smo.Server' is defined in an assembly that is not referenced."
Why does using Microsoft Sql Server Management Objects (SMO) in the DAL require references to SMO dlls in a referenced project?
using sql smo in referenced projects
sql smo in layered solutions
sql smo reference requirements
and probably a few others and have not found a solution or explanation to this issue.
Admittedly, I'm only a journeyman googler, so if someone wishes to power level me and point the way to an existing resource, I'll gladly go spelunking from there.
Here's my set up:
I've got a layered solution: DAL, Business Logic, Services, UI. There's a hosts project that hosts the services. I'm actually using the VS2010 extension layerguidance.codeplex.com, which is quite nice, to set up all these projects. I'm using SQL Server 2008 Express and SMO v 10. All solution projects are referenced using Project References. All projects compile to a common top level Bin folder.
Now the problem:
Among the classes in the DAL I have an SmoTasks class which handles interfacing with SMO objects and a Utilities class which abstracts from SmoTasks and provides acces to its functions without requiring any SMO objects for parameters, so that referencing projects (read: Business Logic Layer) can interface using non-SMO types. All is well in the DAL, it compiles fine, the methods pass their tests - it feels good about its place in my world. Then in the BLL I have a component which handles using the Utilities class to perform database configuration for the application which will be exposed via the services. The BLL uses a project reference to the DAL and sees the DAL classes (a la intellisense) as expected. When I compile though, I get:
The type 'Microsoft.SqlServer.Management.Smo.Server' is defined in an assembly that is not referenced. You must add a reference to assembly 'Microsoft.SqlServer.Smo, Version=10.0.0.0, Culture=neutral, PublicKeyToken=89845dcd8080cc91'.
The code in BLL looks like this:
public bool CreateTables(string connectionString)
{
bool result = default(bool);
// Data access component declarations.
Utilities utilities = new Utilities();
// Step 1 - Calling CreateTables on Utilities.
result = utilities.CreateTables(connectionString);
return result;
}
The line the error points to is:
result = utilities.CreateTables(connectionString);
I could, obviously, add the SMO references to the BLL and then the BLL would be happy, but that violates my design goal of loosely coupled projects. If I add the SMO assemblies to the BLL, it compiles and then referencing BLL objects in the services layer doesn't cause a complaint. My question is, why? More specifically: Why does the BLL need references to SMO when the Utilities class in the DAL already abstracts away the SMO types?
What I want is everything database related to live in the DAL (duh) and only business logic in the BLL (double duh). Is there another way to achieve this using SMO that I have overlooked?
Thank you for your valuable time and answers, I humbly await your responses
Edit:
I've adjusted my solution based on suggestions by Chris, verified that I'm using project refs (I am), readded the references to SMO in the DAL using Muse.VSExtensions to add GAC reference, before I had been browsing and adding manually, then I went ahead and set Copy Local = True for those assemblies just to be doubly sure they're around... but I'm still stuck with this annoying compile error.
I think this boils down to how things are referenced in your solution. So I'm going to take a couple guesses.
It sounds like your DLL references the DAL as an assembly instead of as a project reference.
During compile time Visual Studio copies everything it thinks is necessary to the projects BIN directory. If you reference an external DLL (DAL) then it will copy that DLL only to your BLL's BIN directory.
What you need to do is get it to copy the SMO assemblies as well OR have those SMO assemblies available through the GAC. Personally, I don't like GAC'ing things, so I'll ignore that.
There are three ways of doing this. The easiest is to simply add a reference to those other assemblies to your BLL. Obviously that's not what you want.
The second way is to reference the DAL project as a project reference. This will allow Visual Studio to detect the extra dependencies and copy them accordingly. This is also not exactly what you want as well.
The third way is to copy them as part of a build step. Right click on your BLL project and go to Build Events. In the Pre-build event command line put in the commands to copy the necessary SMO files to your BLL projects BIN directory.
You'll have to do this again for the main service project as well.
It's depressing to answer your own question with a mea culpa, "I'm an idiot"... but, well, I'm an idiot:
In Utilities there was an overload for the offending method which did contain an Smo.Server parameter. I removed that overload (an artifact from testing before refactoring) and voila, problem solved/idiocy confirmed! The interesting thing I learned here is that using the other methods of the Utilities class, which did not have overloads containing Smo objects, was absolutely fine, meaning even with a function in the Utilities class which required an Smo object for a parameter, as long as I didn't call that method or one of its overloads, the references resolved perfectly without a hitch. The new question I have, is why? Why does that overload's existence matter for reference resolution if I call another version of that function from a project higher in the dependency chain? Is there some internal loop where it goes over all versions of a function checking references if any version has been called...
My C# project - we'll call it the SuperUI - used to make use of a class from an external assembly. Now it doesn't, but the compiler won't let me build the project without the assembly reference in place. Let me elaborate.
This project used to throw and catch a custom exception class - the SuperException - which was derived from the standard System.Exception and lived in a separate, precompiled assembly, SuperAssembly.DLL, which I referenced.
Eventually, I decided this was a pointless exercise and replaced all SuperExceptions with a System.SuitableStandardException in each case. I removed the reference to SuperException.DLL, but am now met with the following on trying to compile the project:
The type 'SuperException' is defined in an assembly that is not referenced. You must add a reference to assembly 'SuperException, Version=1.1.0.0 (...)'
The source file referenced by the error doesn't seem relevant; it's the project namespace that gets highlighted in the IDE.
Now, here's the thing:
All uses of SuperException have been eliminated from the project's code.
Compared to another project that compiles fine without a reference to SuperException.DLL, I only reference one more assembly - and that references nothing that my project doesn't reference itself. While it's possible that any of these dependencies could throw SuperExceptions, I'm only catching the base Exception class and in any case... the other project builds fine!
I've done Visual Studio's "Clean Solution" and cleared everything out by hand, many times.
It's not the end of the world to include this reference, I just don't see why it's necessary any more. Nrrrgg. Any pointers welcome!
It's likely a transitive reference, where some type method call returns an instance of SuperException boxed ("downcast") as e.g. Exception, but from inspecting the code in the transitively included code, i.e. code from your external method calls, the compiler knows that you need to be able to have information about that type at some point.
Resharper would tell you where it's the case that you need to add a reference, and you could use Lütz Roeder's aka RedGate's Reflector to scan compiled IL for a reference to this type in two ways: 1) use the search-facility, 2) open each public type you're using and for that one which requires the "ghost" assembly, it will ask you to specify its location.
This most often happends to me when I reference Castle.Windsor but not Castle.MicroKernel. :p
Exit Visual Studio
Delete the bin and obj Folders in your solution directory
Restart and see what happens
I agree with the other comments here.. There is a reference, in plain text somewhere !
I have had similar problems in the past where searching through the project files returned nothing, turns out it was in some other file that wasn't automatically picked up in the search.
I don't think that creating a new project is the solution here.. You need to be positive that NONE of the references in your dependency tree use SuperException.. NONE
I have never experienced this to the point where I have needed to literally wipe the project, I have always found the reference somewhere. Ensure you are searching every file.
EDIT:
Just a point to add, if the location pointed to by the error seems random, that can often mean there is a mismatch between the compiled source and the source code file.. Is this a ASP.NET application? I have had it before where the compiled DLL's haven't been replaced on a rebuild in the ASP.NET temp folder causing things to get.. Interesting when debugging :)
I don't think this is a code issue. What I can see happening is that one of your existing references probably rely on that type in their own types which you are probably creating in your application.
If that is the case you do need that reference even if you don't explicitly use the type and even though the other referenced assembly has its own reference. You sometimes get that issue with 3rd party components which need references to types that you haven't referenced. The compiler is obviously seeing something in one of your existing referenced assemblies and is expecting you to referenced the dependent one.
Since it's a compiler error, there must be a reference or use of SuperException somewhere in the project.
Do a find/replace in the entire project or solution for that type and remove every reference (it's possible you already did this).
If you reference any types that inherits from SuperException (even if the type defined in another assembly), you need a reference to the assembly that SuperException is defined in.
Take the line that the compiler is showing the error on and start tracing the inheritance tree of the objects used on that line, you might find the source of it that way.
Thanks for your answers so far. I've tried every suggestion (except one) to no avail.
The suggestion I haven't tried is to create a new project and add all my stuff to it, the thought of which really tests my will to live. ;) I may try this tomorrow if I can be bothered. Thanks again.
There is really nothing very mysterious about VS projects nowadays - it's all text files, etc. SOMETHING must reference that class/dll, and that something must be part of your project.
Have you really grep'd or findstr'd the whole solution tree, every single file, for a reference to that exception?
This sounds pretty strange. Here's what I would check next:
Check that there's nothing lingering in your Properties/AssemblyInfo.cs file.
Check that there's nothing lingering in your SuperUI.csproj file.
Delete all references and re-add them.
Try creating a new project, and adding all your classes to it.
grep your project folder. It could be a hidden reference in your project, or a project that your project references. Cleanse with Notepad if needed.
If you reference any types that inherits from SuperException (even if the type defined in another assembly), you need a reference to the assembly that SuperException is defined in.
Seconded on that.
You might not be referencing SuperException, but you might be referencing SpecializedSuperException, which is derived from, or somehow otherwise uses SuperException - your grep of the project for SuperException won't be catching it though.
Try have a hack with the trial of NDepend
This is where tools like Resharper really pay off -- a simple Find Usages usually tells me of such "ghost dependencies" several times.
Maybe you could go to your definition of the SuperException class and try to Find All References(). You might also want to investigate if the assembly SuperException is has a circular dependency on your main assembly (e.g., main assembly depends on exception assembly depends on main assembly...).
I’ve had a very similar assembly reference issue that was happening when my C# library had a dependent C++/CLI assembly.
The problem that was I was inheriting a public class from that C++/CLI assembly in my C# assembly library. That meant that the inheritance chain was spanning across multiple assemblies.
I was hoping that any client would be smart enough to indirectly load the C++/CLI assembly any time the C# library needed it, but that was not the case even at compile time.
I got rid of this problem by breaking the inheritance between the classes that were spanning across those two assembly libraries and using aggregation instead.
My client was finally happy and did not require the C++/CLI assembly as a dependency anymore.
In your word you would probably have to make sure that SuitableStandardException does not inherit from SuperException in order to eliminate the SuperException.DLL as a reference.
Use encapsulation instead of inheritance and create a SuperException data member in your new SuitableStandardException.
If that does not solve it, you might have more classes spanning inheritance across some assemblies, in your case SuperAssembly.DLL and superException.dll.
If you can't find all of them try this trick:
Make all your public members and classes in SuperAssembly.DLL internal.
In the SuperAssembly.DLL make friends with SuperException.DLL:
[assembly:InternalsVisibleTo("SuperException, PublicKey=0024000004800000....)]
Make sure that they build and remove the SuperAssembly.DLL reference from any client that already references SuperException.DLL.
grep -R SuperException * in the base of your project (get grep from somewhere first) just to be sure.