Create an instance from an assembly and its dependencies in C #

I have an application (let’s just call it MyApp) that dynamically creates the source code for the class and then compiles it. When it compiles the source code, I also refer to another DLL (this is the base class for this newly created class), which already exists in another folder. To compile and output the DLL, I do the following:

//Create a C# code provider CodeDomProvider provider = CodeDomProvider.CreateProvider("CSharp"); //Set the complier parameters CompilerParameters cp = new CompilerParameters(); cp.GenerateExecutable = false; cp.GenerateInMemory = false; cp.TreatWarningsAsErrors = false; cp.WarningLevel = 3; cp.OutputAssembly = "SomeOutputPathForDLL"; // Include referenced assemblies cp.ReferencedAssemblies.Add("mscorlib.dll"); cp.ReferencedAssemblies.Add("System.dll"); cp.ReferencedAssemblies.Add("System.Core.dll"); cp.ReferencedAssemblies.Add("System.Data.dll"); cp.ReferencedAssemblies.Add("System.Data.DataSetExtensions.dll"); cp.ReferencedAssemblies.Add("System.Xml.dll"); cp.ReferencedAssemblies.Add("System.Xml.Linq.dll"); cp.ReferencedAssemblies.Add("MyApp.exe"); cp.ReferencedAssemblies.Add("SomeFolder\SomeAdditionalReferencedDLL.dll"); // Set the compiler options cp.CompilerOptions = "/target:library /optimize"; CompilerResults cr = provider.CompileAssemblyFromFile(cp, "PathToSourceCodeFile"); 

Later in my application (or the next time the application starts) I try to create an instance of the class. I know where the DLL is for the newly created class (let it be called Blah), and the base class. I use the following code to try to instantiate a new class:

 Assembly assembly = Assembly.LoadFile("PathToNewClassDLL"); Blah newBlah = assembly.CreateInstance("MyApp.BlahNamespace.Blah") as Blah; 

When I call Assembly.CreateInstance, as I do above, I get a message that it cannot create an instance. When I check assembly.GetReferencedAssemblies (), it has standard links and a link for my application (MyApp.exe), but it does not have a reference to the dependent base class that I used when compiling the class initially (SomeAdditionalReferencedDLL.dll).

I know that I need to somehow add a reference to the base class to create an instance, but I'm not sure how to do it. How to create an instance of a class from an assembly when I have an assembly and all its dependencies?

thanks

+4
source share
6 answers

If you manually load an external DLL (assembly), THIS DOES NOT AUTOMATICALLY DOWNLOAD WHAT YOU GET.

So, you will need to create an AssemblyLoader. Code that checks the assembly of links for your assembly and downloads them yourself.

In case of complications associated with link assemblies that are in odd folders on your computer, and not with your compiled DLL, check the AppDomain.CurrentDomain.AssemblyResolve event. (You use it to trick .NET into accepting your assembly loadable even if it is not in the GAC or with your compiled DLL)

Once you have loaded your DLL link using code with code, CreateInstance will work.

+3
source

Are you sure that when it compiled, it referenced an instance of the DLL that, in your opinion, is referenced? It may be a solution to the path somewhere, except where you think that when you instantiate your class, it will no longer be able to find this DLL. I recommend getting the Fusion log of both the compilation process and the type creation to see how these types are resolved.

0
source

I think .Net is trying to find "SomeAdditionalReferencedDLL.dll" in your bunker or GAC. Did you try to execute Assembly.Load for "SomeAdditionalReferencedDLL.dll" before creating a new Blah?

0
source

This is similar to the fact that the assembly you are referencing in a dynamically generated assembly is not included in one of the standard verification paths.

Where is it in relation to everything else?

You must run a fusion log scan to see where everything goes wrong.

0
source

First of all, I think you have circular addiction. Your last paragraph sums up. You need to rethink your application and decide whether your responsibilities are set correctly.

Why cyclic dependency:

To create a new dll, MyApp.exe is required;

MyApp.exe cannot be used without a new dll.

maybe tell us what your goal is, and we can structure your application properly.

With due responsibility, the delegated MyApp.exe must do the work with the new generated assembly; it does not require MyApp.exe to use objects from the new dll.

For example, you should only have Execute on the new generated assembly .....

  public static void RenderTemplate(String templatepath, System.IO.Stream outstream, XElement xml, Dictionary<String, object> otherdata) { var templateFile = System.IO.File.ReadAllText(templatepath); var interpreter = new Interpreter(); interpreter.ReferencedAssemblies.Add("System.Core.dll"); // linq extentions interpreter.ReferencedAssemblies.Add("System.Xml.dll"); interpreter.ReferencedAssemblies.Add("System.Xml.Linq.dll"); interpreter.UsingReferences.Add("System.Linq"); interpreter.UsingReferences.Add("System.Xml"); interpreter.UsingReferences.Add("System.Xml.Linq"); interpreter.UsingReferences.Add("System.Collections.Generic"); interpreter.Execute(templateFile, outstream, xml, otherdata); } 
0
source
 //Constructor static MyClass() { //Provoque l'événement quand .Net ne sait pas retrouver un Assembly référencé AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(CurrentDomain_AssemblyResolve); } /// <summary> /// Mémorise les assembly référencés par d'autres qui ne sont pas dans le répertoire principal d'EDV /// </summary> static Dictionary<string, string> _AssembliesPath; /// <summary> /// .Net ne sait pas retrouver un Assembly référencé /// Cherche et charge d'après les assembly référencés par d'autres qui ne sont pas dans le répertoire principal d'EDV /// </summary> /// <param name="sender"></param> /// <param name="args"></param> /// <returns></returns> static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args) { if (_AssembliesPath != null && _AssembliesPath.ContainsKey(args.Name)) { Assembly lAssembly = Assembly.LoadFile(_AssembliesPath[args.Name]); AddAssemblyReferencedAssemblies(lAssembly, System.IO.Path.GetDirectoryName(lAssembly.Location)); return lAssembly; } Error = string.Format("L'assembly {0} n'a pu être chargé", args.Name); return null; } /// <summary> /// Mémorise les assembly référencés par d'autres qui ne sont pas dans le répertoire principal d'EDV /// </summary> /// <param name="pAssembly"></param> /// <param name="psRootPath"></param> static void AddAssemblyReferencedAssemblies(Assembly pAssembly, string psRootPath) { if (_AssembliesPath == null) _AssembliesPath = new Dictionary<string, string>(); foreach (AssemblyName lRefedAss in pAssembly.GetReferencedAssemblies()) if (!_AssembliesPath.ContainsKey(lRefedAss.FullName)) { string lsRoot = psRootPath + "\\" + lRefedAss.Name + "."; string lsExt; if (System.IO.File.Exists(lsRoot + (lsExt = "dll")) || System.IO.File.Exists(lsRoot + (lsExt = "exe"))) { _AssembliesPath.Add(lRefedAss.FullName, lsRoot + lsExt); } } } 

// call the assembly function lAssembly = Assembly.LoadFile (lsExternalAssemblyPath); AddAssemblyReferencedAssemblies (lAssembly, System.IO.Path.GetDirectoryName (lsExternalAssemblyPath));

0
source

All Articles