1

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?

Pavel Anikhouski
  • 21,776
  • 12
  • 51
  • 66
hunger
  • 413
  • 1
  • 4
  • 12
  • Is 3rd party DLL .NET assembly or not? – Pavel Anikhouski Nov 21 '19 at 15:11
  • @PavelAnikhouski It is indeed a .NET assembly – hunger Nov 21 '19 at 15:15
  • 1
    You can try to load it using `Assembly.LoadFrom` method – Pavel Anikhouski Nov 21 '19 at 15:17
  • Ok. But I guess that would mean not being able to use `using xyz.abc` directives and accessing the namespaces/classes as I would normally. Also using a sandbox or trusting remote resources, see: https://learn.microsoft.com/en-us/dotnet/api/system.reflection.assembly.loadfrom?view=netframework-4.8#remarks But it looks like another feasible approach to consider. Thank you. – hunger Nov 21 '19 at 15:24
  • 1
    Yes, you can't use namespaces, all code is loaded dynamically. But you can place your DLL somewhere outside repo with source code – Pavel Anikhouski Nov 21 '19 at 15:44

2 Answers2

1

Load it using the Assembly.LoadFrom method. That should work!

jojasicek
  • 11
  • 4
1

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

Pavel Anikhouski
  • 21,776
  • 12
  • 51
  • 66
  • Do you know if that has any performance disadvantage compared to "normal" binding? I don't care about initialization time, but rather about subsequent calls on an object I instantiated from the DLL. – hunger Nov 21 '19 at 16:20
  • 1
    @hunger In general reflection is slower than normal method call, because of some security and other runtime checks. But for the subsequent reflection calls you can use delegate and achieve almost the same performance. https://www.c-sharpcorner.com/article/boosting-up-the-reflection-performance-in-c-sharp/ there is a simple example how to do that – Pavel Anikhouski Nov 21 '19 at 16:40
  • @hunger Does it answer your question, any more points to consider here?:) – Pavel Anikhouski Nov 22 '19 at 11:45
  • It answers the question, thank you. I'm now trying to use delegates to speed up execution; the problem is that the method I want to call returns a type that is also defined in the generated in the external DLL. Do you know how I can declare/define such a delegate? `Type retType = ReturnTypeFromExternalDLL; Func ...` this does not work. – hunger Nov 22 '19 at 13:38
  • How do I supply the class of `retType` as a generic argument to `Func<>`? – hunger Nov 22 '19 at 13:47
  • 1
    Yes, it's possible, `MakeGenericMethod` will help you, look at existing threads [here](https://stackoverflow.com/questions/2107845/generics-in-c-using-type-of-a-variable-as-parameter) and [here](https://stackoverflow.com/questions/266115/pass-an-instantiated-system-type-as-a-type-parameter-for-a-generic-class) – Pavel Anikhouski Nov 22 '19 at 14:01