TheSwamp

Code Red => .NET => Topic started by: Jeff_M on April 09, 2020, 12:52:32 PM

Title: How to use a method in another Assembly?
Post by: Jeff_M on April 09, 2020, 12:52:32 PM
I have 2 projects. In the first I am checking to see if Civil 3D is the currently running application. If it is, I load the second Assembly and use a Method in it which returns a single integer. If I include the second project in the References of the first it works fine since the namespace and class can be seen. However, when it is referenced and built, the C3D assemblies get copied into the build folder even though they are set to not copy Local. This prevents the tool from running outside of Civil 3D (such as plain Autocad). So what I need to do is be able to call that method with Reflection, but I'm having a difficult time getting the right format.
Code - C#: [Select]
  1.                     var assy = LoadExtension(Name); //This works, assembly is loaded
  2.                     unitType = (int)assy.GetType().InvokeMember("GetC3DScalesInt", BindingFlags.InvokeMethod,null, assy, null); //This fails, as does the following with the namespace and class included
  3.                     unitType = (int)assy.GetType().InvokeMember("C3DPortion.GetC3DScales.GetC3DScalesInt", BindingFlags.InvokeMethod,null, assy, null);
  4.  
Can this even be done? Am I barking up the wrong tree?

Thanks!
Title: Re: How to use a method in another Assembly?
Post by: huiz on April 09, 2020, 01:22:12 PM
Yes, no problem. I do this with a second project to attach Object Data and Property Sets, which can't be done in plain AutoCAD.
Later I will add my code, I am on my mobile phone now.
Title: Re: How to use a method in another Assembly?
Post by: huiz on April 09, 2020, 01:40:45 PM
Ok, why not adding the code right now :-)




I have two projects. Project 1 is the main dll, Project 2 is a dll with just code that works in Civil 3D or Map 3D.


Project 1: Do not reference Project 2. Only create a new command or a right mouse button menu item or so. There you check if you are running inside Civil 3D and if not, you can show a nice message.


If you are running inside Civil 3D you can load the seperate dll and call the function you need:






Code: [Select]



#if DEBUG
                    string dllFile = FileSystem.Functions.GetMyPath() + @"..\..\..\Project 2\bin\Debug\Project2.dll";
#else
                    string dllFile = FileSystem.Functions.GetMyPath() + "Project2.dll";
#endif


                    if (FileSystem.Functions.FileExist(dllFile) == false)
                    {
                        return ExportResult.ModuleNotFound;
                    }


                    // Load the dll
                    Assembly assembly = Assembly.LoadFrom(dllFile);
                    System.Type assemblyClass = assembly.GetType("Project2");


                    if (assemblyClass == null)
                    {
                        return ExportResult.ModuleNotFound;
                    }


                    // var methodInfo = t.GetMethod("MyFunction", new Type[] { typeof(int), typeof(string) });
                    MethodInfo methodInfo = assemblyClass.GetMethod("MyFunction"); // I don't use parameters here


                    if (methodInfo == null)
                    {
                        return ExportResult.FunctionNotFound;
                    }


                    // object[] constructorParameters = new object[0];
                    // constructorParameters[0] = 999; // First parameter.
                    // constructorParameters[1] = 2;   // Second parameter.


                    // Create Instance of the Class (Constructor)
                    object instance = System.Activator.CreateInstance(assemblyClass, null); // No parameters needed for the constructor so I use null


                    // Function parameters
                    object[] parameters = new object[2];
                    parameters[0] = objectIds;
                    parameters[1] = dataTable;


                    // Run Method with optional parameters (I feed it with objectids and a datatable) en get result back (in this case I return a bool)
                    bool success = System.Convert.ToBoolean(methodInfo.Invoke(instance, parameters));


                    if (success == true)
                    {
                        return ExportResult.Correct;
                    }




Works quite good.

Title: Re: How to use a method in another Assembly?
Post by: Jeff_M on April 09, 2020, 02:03:50 PM
Thank you, huiz! What does the beginning of your 2nd dll class look like? I'm getting null for the assemblyClass...I used the assembly name, and the class name, both return null so I must be missing something in that class. Scratch that, I figured out I had to use the Namespace and the class:
 
Code - C#: [Select]
  1. Type assemblyClass = assembly.GetType("C3DPortion.GetC3DScales");

Now working perfectly, thanks again!
Title: Re: How to use a method in another Assembly?
Post by: huiz on April 09, 2020, 02:55:01 PM
I'm glad I could help :-)