C# Hidden References - c#

I am trying to determine which dlls my assemblies need to compile. I have two sample projects, Scratch and ScratchTest both in one solution. Here is Scratch's Program.cs:
using System.ServiceProcess;
namespace Scratch
{
public class A : ServiceBase
{
static void Main(string[] args)
{
}
}
}
Scratch has a reference to System.ServiceProcess.dll.
Here is ScratchTest's program.cs:
namespace ScratchTest
{
class Program
{
static void Main(string[] args)
{
Scratch.A o;
}
}
}
ScratchTest has to reference BOTH Scratch and System.ServiceProcess.dll. However, the resulting ScratchTest.dll has no reference to System.ServiceProcess.dll, only Scratch. I know this both by looking at
Assembly.GetReferencedAssemblies()
and by using .net reflector. So my question is, how can I tell that ScratchTest requires System.ServiceProcess.dll to compile? Especially considering SratchTest wouldn't necessarily want to reference all of Scratch's references because there might be some conflicting ones. Thanks, Eric

First thing is that the problem that you are facing is not specific to ServiceBase Class. It is pertaining to how exactly CLR detects the type dependencies for a C# program and loads the referenced assemblies. C# compiler is simply giving you an error in advance at compile time itself as the same will fail at run time also when CLR tries to run your program. Here is what I'm assuming while explaining the solution to your problem:
ScratchTest is your start-up project although you have defined two entry points in your solution as Main method is present in both "Scratch" and "ScratchTest" projects. To avoid confusion generally you should have only one main method (entry point) for your solution though it has no impact on your current problem.
Solution : When you refer class A in scratchTest project you are not referring only to class A but the class ServiceBase as well because class "A" is inheriting from it. So when compiler tries to compile your ScratchTest Project it tries to find the dependency types namely "A" and ServiceBase both in the assemblies that are currently referenced. The point of importance here is that CLR always tries to find the dependency types only in the assemblies whose reference is present directly in the manifest meta-data of the assembly itself which you are trying to load (which is ScratchTest in this case). Dependency types are NEVER searched in a recursive fashion the way you have structured your solution. Essentially expecting CLR to search a dependency type in all the referenced assemblies and in turn their referenced assemblies will be hell lot of performance impact at start-up of your .Net application.
At the same time the core .Net libraries like MsCorLib, System, System.Core, System.Data are usually referenced in most of the C# projects you create. Then considering the case otherwise had CLR implemented the logic of recursively finding the dependency types through referenced assemblies then it would have been making an extra effort by making a check every time whether it had already gone past a specific assembly or not while searching a dependency type which would have hurt start-up performance further.
To fix your code you can do following two things :
Add reference to System.ServiceProcess.dll to ScratchTest project as advised by the C# compiler.
OR
Use the class A in "ScratchTest" project itself as it already contains a reference to System.ServiceProcess.dll

I don't think you need to explicit call System.ServiceProcess on the test file.
The Test file is not using any reference to any method or class inside System.ServiceProcess, just using Scratch.
You do not need to requieres all the libraries that the referenced clases uses, just the one are currently used by your class.
So ScratchTest is only using Scrath and Scratch is using System.ServiceProcess.

Related

Global using directive in c#

I'd like to create a namespace in c# that can be found in any project. Not just the one that it is located in. like the system namespace. Is that possible and if yes I'd like to know how.
I already googled and didn't find anything
Classes in the System namespace are part of the Base Class Library (BCL) that gets included as part of the .NET Runtime. The only way for you to have your class be as globally accessible as, say, the System.String class, would be to convince Microsoft to add your class into their BCL. That is rare, but not unheard of. The IObservable<> interface is an example of a type that was added that way.
However, there are tons of classes that people are using every day without having them added to the BCL. If you're willing to accept one additional step for people to take with their projects, in order to leverage your project, you can publish your project's output as a Nuget package. Then people only need to add your Nuget package (referenced by its package name), and they'll have access to the public API defined by the types in your DLLs.
Consumers of your package will still need to reference the namespaces of the types they want to use, either explicitly or via a using directive. In C#, a "global using directive" only makes the namespace globally available within the project that the directive is found in.
If you only want your types to be accessible from other projects found in the same solution, Nuget isn't necessary: you can add a project reference.
There are a lot of nuances I'm glossing over (i.e. differences between namespaces and DLLs and packages), but which it would be helpful for you to read about.
One of solution:
You need to create library(DLL) and refernce it in projects.
If you using visual studio 201x you can create project with type class library.
The library namespaces can be found use like this ´using MyNamespace;´
example of class in library:
adding refernce to project:
example of using your own class library:

Comparing project classes against a compiled dll using IsSubclassOf

C# DLL referencing comparing question.
I have a Multiple project solution - all are DLLs
All of the projects (except the first dll), are optional DLLS that refence the first one since these are 'addons' to the first DLL.
Lets say the first and main DLL has a class called 'Base'.
The other DLLS have a class that inherit from this one.
With that in mind, I have this code:
Assembly assembly = Assembly.LoadFrom("second.dll");
foreach (Type type in assembly.GetTypes());
{
// In the itiration of classes, the one inhereting from Base class will come,
// but the compiler won't recognize it, even if in debug they do appear to be so.
if (type.IsSubclassOf(typeof(Base))
// Successful code here
}
}
All of the dependent DLLs are Built first before passing execution to the Base DLL.
Any ideas?

Please can someone explain how to use namespace/assemblies in project development for sharing classes between programs

Can you use namespaces in one program to get the classes from those other programs in your program? Or do you do this using assemblies? And how do you do it?
To use classes defined in another program (let us call this program an "assembly"), you can reference that assembly in your program/application and use the classes. The classes have to be defined as public in that other assembly.
An assembly is basically an .exe or a .dll, as explained in this answer.
Usually classes that are meant to be reused are defined in a class library and compiled to a .dll.
The goal of namespaces is to separate the code into meaningful pieces, as explained here.
A namespace creates a sort of "full name" for a class. So, in you program you will have to reference a class defined in another program/assembly by its full name, meaning using its namespace and its class name.
If you are trying to use code from one c# project in other you just need to add a reference in the project you are going to consume the code to the project with the code to be consumed.
If you are trying to consume code from an already compiled assembly and this compiled assembly is .net you can either use reflection or .net decompiler to get the code.
Jetbrains have a .net decompiler.

Why must an assembly be referenced twice?

Question
It seems to me that any time I make a class library, all of its dependencies should just come with it. In other words, I would expect to just reference a .dll and go. After all, the .dll I reference builds just fine on its own.
Is this not the case? I reference all of a dependency's dependencies, in order to use it?
Looking forward to being enlightened about this.
Issue
To illustrate, here's an example.
ClassLibrary1 is a class library project, with one public class:
Class1.
ClassLibrary2 is another class library, in the same solution, with
one public class: Class1.
These two classes exist in their own namespaces.
However, ClassLibrary2 references ClassLibrary1, and ClassLibrary2.Class1 inherits from ClassLibrary1.Class1.
ConsoleApplication1 is a console app, in the same solution, that references only ClassLibrary2.
Up to this point, everything builds. Everything is the same framework.
However, when I attempt to initiate ClassLibrary2.Class1, I get a build error:
Error 1 The type 'ClassLibrary1.Class1' is defined in an assembly that
is not referenced. You must add a reference to assembly
'ClassLibrary1, Version=1.0.0.0, Culture=neutral,
PublicKeyToken=null'. ...\ConsoleApplication1\Program.cs 12 4 ConsoleApplication1
Code Snippets
namespace ClassLibrary1
{
public class Class1
{
public Class1() { }
}
}
...
namespace ClassLibrary2
{
public class Class1 : ClassLibrary1.Class1
{
public Class1() : base() { }
}
}
...
namespace ConsoleApplication1
{
using ClassLibrary2;
class Program
{
static void Main(string[] args)
{
// error mentioned previously in post is on following line
var a = new Class1();
}
}
}
I'll try to formulate an answer here. It helps to look at dependencies on the project level in VS and hopefully it will be more clear.
Suppose you have two projects, ProjectA and ProjectB in a solution. Both projects reference an assembly Important.dll. By reference here, I am referring to if you right click -> Add 'Reference' in a VS project. Suppose also, that ProjectA references ProjectB in our solution in VS. By this I mean, right click -> 'Add Reference' -> 'Solution' -> Pick Project B
What is actually going on? Remember, all a VS reference is a way to help the compiler find the .dll. At build time (compiling), VS will go through all the projects in the solution that are required to be built (you can see this in the Configuration Manager). It will notice that both ProjectA and ProjectB are set to build. Then it will look at all its direct dependencies in the references section by traversing the dependency tree. For all the VS references that are set to 'Copy local' (true by default), they will be sent to the build folder. So Important.dll will go to the build folder.. you probably knew that.
But ProjectA references ProjectB in VS. When you have a project that references another project in a solution, all you're really doing is pointing to the built .dll of that project... in this case ProjectB.dll. It's no different from antoher .dll. You can see this if you look at the references section under 'Path' in ProjectA... it'll be something like C:\users\jdwqdwqd\vs\ProjectB\ProjectB\bin\x64\ProjectB.dll. So this will be copied to the output folder as well.
I guess one might ask 'Won't Important.dll be copied twice along with ProjectB.dll?. VS gives you a lot of help here and will pick the correct .dll to copy.
Hope this helps.
Some more information:
https://msdn.microsoft.com/en-us/library/ez524kew.aspx
It's just the way C# works. The inheritance rules seem to be skewed. I'm working on a massive project at work, and I can use class libraries and namespaces across multiple files, but I have to reference them every time, regardless of inheritance. It's weird and annoying. Maybe they'll fix that soon.

Lingering assembly dependency in C# .NET

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.

Categories

Resources