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?
Related
I have a project that must reference and call a DLL which is created by executing a 3rd party executable every time a build is triggered. (A proxy-DLL that is created from a JAR file to enable calling Java-Code from within C#. Done using proxygen from jni4net, but that's not important. The JAR file might change from time to time, but its calling interface stays the same).
I also need to instantiate an object from a class from the DLL and call methods on the object.
I have 2 approaches in mind:
1) Run it as a pre-build step in the same project. But this means I have to include a DLL in the repository and add that DLL as a reference to the project, so that C# knows that my calls are valid. And that means that I'll have a "stale" DLL in my repo and everytime a build is triggered, the SCM detects it as changed.
2) Create a dummy DLL project, e.g. with a dummy C# file, and then execute the program in a post-build step to overwrite the dummy DLL with the actual DLL. I could then add this as a normal project dependency. I would then have to implement dummy calls in the C# for the actual calls that are later in the "real" DLL so that the other project doesn't complain about the calls. But I wouldn't have to include a stale DLL in the repository.
Is there a better, more elegant solution?
Since your 3rd party assembly is .NET one, you can place outside your source code repo, and load dynamically using Assembly.LoadFrom method. After that you can list a types from loaded assembly using GetTypes method
Activator.CreateInstance(Type) can help to create an object using loaded type.
This is called reflection. You can also invoke a method or pass arguments to constructor, have a look at MSDN for some examples
Load it using the Assembly.LoadFrom method. That should work!
My project(some kind of processing engine) is separated into 2 dlls: one with interface declarations and one with functionality.Usually the project is used by external Delphi project via COM technology.
Lets say my program slices fruits. External delphi programm creates Fruit object and fills its properties: weight (int), Name (string) and ProgressUpdater (of type IProgressUpdater which is declared in second dll with interfaces).After this exst programm creater Slicer, makes Slicer.AddFruit(newFruit) and calls Slicer.Slice().
Nothing special. In real life delphi project is Outlook addin. But here is the problem - sometimes some VSTO addins makes Outlook work in "shadow copy files" mode, so when delphi project starts and creats Slicer object, our c# assembly will be put in temp folder and assembly will be created with this local path. Well... this is still not an issue. But the problem is when delphi project creates newFruit and then passes ProgressUpdater object, in my Slicer assembly I can not get external ProgressUpdater: "Return argument has an invalid type", but still can get field with simple types(Weight, Name).
It only happens when shadowCopyFiles mode is on. So my guess is - external ProgressUpdater's assembly and Slicer assembly are placed to different places, so they can not be passed. My question is how to avoid my dll being "shadow copied"? Or is there some different solution?
So as a result I still have no answer for exact question. But the problem is solved (thanks to HansPassant) by using GAC, because assemblies at GAC will be never shadow-copied (actually linker will always first probe assemblies in GAC and then in other places).
Possible answer to the question is to go currentDomain.AssemblyResolve way, but I could not apply this solution to dll which contains public interfaces(types) only. Maybe it will be suitable solution for some cases.
You can use reflection to load DLL dynamically from any location you want. If you can go this way, I can provide further code for loading DLLs.
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.
I am embedding a script engine based on Roslyn into my application and started facing some issues. When loading a reference into my engine, I do the following
var engine = new Roslyn.Scripting.CSharp.ScriptEngine();
engine.AddReference("MyAssemblyLocation");
Questions:
If MyAssemblyLocation assembly is referencing other assemblies, how do I tell Roslyn to load them without doing an engine.AddReference("MyAssemblyLocation");
The host application in which the script is supposed to be running has already loaded some assemblies I would like to use in the script, is there a way for Roslyn to hook itself into the already loaded dlls in memory and not load new instances?
Finally, is there a way to tell Roslyn to recursively load all dependencies of MyAssemblyLocation
Thank you.
1) Short answer: you need to AddReference on all assemblies whose types are you going to use in the script.
Details:
The C# compiler doesn't guess where the dependent files are. An assembly file doesn't specify full paths to all of its dependencies. It only contains their names and that's generally not enough for the compiler to be able to locate the assembly file.
More details:
There are two kinds of dependencies. I'll call them compile time dependencies (a) and runtime dependencies (b).
(a) Suppose you have "public class A : B {}" in assembly A.dll, "public class B { }" in assembly B.dll, and your script is using A, say you create a new instance: "new A()". The compiler requires you to add references to both A.dll and B.dll in this case, since A derives from B and the compiler needs to analyze the inheritance hierarchy of each type you use. So B.dll is a compile-time dependency of your script - the compiler needs it in order to analyze your script properly.
(b) Consider another example: "public class A { public object M() { return new B(); } }" in A.dll and the same B.dll as above. Now when compiling "new A().M()" the compiler doesn't need to know about B, since the reference to B only occurs in the body of method M and the compiler doesn't analyze bodies of imported methods. In this case it suffices to add a reference to A.dll in order to compile the script. When the script executes it calls method M. At that point the CLR loads assembly B. This gets a bit complex, so I'll skip details but in common scenarios we'll be able to locate the assembly for you, so you don't need to add the reference explicitly.
2) I'd recommend using the overload of AddReference that takes Assembly object. Something like:
engine.AddReference(typeof(SomeTypeInAssemblyFoo).Assembly) to load assembly Foo that contains type SomeTypeInAssemblyFoo.
3) Not a straightforward one. You can enumerate all references using Reflection or Roslyn APIs and load each one of them.
Feel free to ask further questions if the explanation is not clear or you wish to know more details.
In msvc i can write
#pragma comment(lib, "my.lib");
which includes my.lib in the linking stage. In my solution i have 2 projects. One is a class project the other is my main. How do i include the reference dll in code instead of adding the reference in the project?
Contrary to popular belief, it is possible :-)
To statically link .NET assemblies check out ILMerge. It's a utility that can be used to merge multiple .NET assemblies into a single one. Be it an executable or a DLL.
You could create a batch script that packages your assemblies together as a post-build step.
Edit: One thing to note however is that this does not remove the need to reference the library. The reference is still needed in order to compile your code that is dependent the external types. Much like including header files under C(++). By default c# assemblies are independent, there is no linking involved. However the tool I mentioned above allows you to create a new assembly with the external dependencies included.
As far as I know, you can't. If you need to access type that are included in a non referenced assembly, you'll have to use Assembly.Load().
I'm afraid you can't.
You can dynamically load the assembly via Assembly.Load(...) but then you have use reflection to explicitly create each Type you need to use.
I don't think you can include a dll from code without adding a reference. What you can do however is to use reflection to load that assembly and use a type from that assembly.
Assembly.Load() will get you a handle on the assembly and then you should be able to iterate through the types in the assembly.
Managed code doesn't use a linker. The C/C++ equivalent of a reference assembly is the #include directive, you need that in C/C++ to allow the compiler to generate code for an external type. Exact same thing in C#, you can't use an external type unless the compiler has a definition for it. The reference assembly supplies that.
The equivalent of C/C++ linking is done at runtime in a managed program. The JIT compiler loads assemblies as needed to generate machine code.
One thing you can do in a C# program that you can't do in a C/C++ program is using Reflection. It allows you to invoke a constructor and call a type's methods with type and method names as strings. Start that ball rolling with Assembly.GetType() and the methods of the Type class. However, consider a plug-in model with, say, the System.AddIn namespace first.
If you want to load an assembly at runtime, you can use Assembly.LoadFrom(filePath). But that way you are not referencing the assembly, and you can't use strong typing.
For example, you can have different plugins implementing a known interface (the one which is in a separate, referenced assembly), and have them all placed in a folder. Then you can check the folder and load all implementing classes at runtime (like in this example).