oleg-shilo / cs-script

C# scripting platform
http://www.cs-script.net
MIT License
1.56k stars 234 forks source link

error css_reference the compiled cs-script assembly #337

Closed AzizDZH closed 12 months ago

AzizDZH commented 1 year ago

I use cs-script in hosted app .Net 6.0 I've script A and B, in B script I added css_reference to A compiled assembly. I compiled the A script using CompileCode showing the rootclass I compiled the B script using CompileAssemblyFromFile and when I start using var asm = new UnloadableAssembly(); dynamic script = asm.LoadFromAssemblyPath(Bfilepath).CreateObject(""); it gives error that class with give name System.IO.FileNotFoundException: 'Could not load file or assembly 'ℛ94128674-064b-4a19-bb52-27be4a47a9c8#1-0.

what's wrong? could we add reference in script to the compiled script assembly?

AzizDZH commented 1 year ago
var info = new CompileInfo
            {
                RootClass = "AccountingScript",
                AssemblyFile = "D:\\AccountingScript.dll",
            };

var accounting_assm2 = CSScript.Evaluator
                .With(e => e.IsCachingEnabled = false)
                .CompileCode(@"public class TXBase
                             {
                                 public string TranId { get; set; }
                                 public string HashKey { get; set; }
                             }", info); 

dynamic script1 = CSScript.Evaluator
                .ReferenceAssembly(accounting_assm2)
                .LoadCode(@"public class TXPayment 
                            {
                                public string Reason { get; set; }
                                public string Test()
                                {
                                    var tx = new AccountingScript.TXBase();
                                    tx.TranId = ""1"";
                                    return tx.TranId;
                                }
                            }");
*string r = script1.Test().ToString(); // here gives error*
oleg-shilo commented 1 year ago

It is a Roslyn limitation. It does not allow referencing assemblies unless they are loaded from the file. You need either use CompileAssemblyFromFile for both scripts or instead of .ReferenceAssembly(accounting_assm2) use .ReferenceAssembly(info.AssemblyFile).

oleg-shilo commented 1 year ago

Though your very sample without changes works just fine if pasted in the u-test module (EvaluatorTests.Generic_Roalyn.referencing_script_types_from_another_script()).

I suggest you look at that sample and see what is different compared to your sample. One thing that I would advise is to control what assemblies are loaded from the domain. So it's better to disable auto-referencing:

 CSScript.EvaluatorConfig.ReferenceDomainAssemblies = false; // to avoid an accidental referencing
AzizDZH commented 1 year ago

my idea was to compile each script to assemblies, each could reference to other by assemblies. and create instance of any when needed. Unloaded it after use. so I could renew any assembly at runtime. I've compiled each script to assemblies using CompileAssemblyFromFile and when I create an instance of assembly (asm.LoadFromAssemblyPath) that has a reference to another (asm.LoadFromAssemblyPath) one it gives that error.

AzizDZH commented 1 year ago

Code below that taken from the u-test module fails with the same error var info = new CompileInfo { RootClass = "script_a", AssemblyFile = "D:\scriptA.dll", }; var accounting_assm2 = CSScript.RoslynEvaluator .With(e => e.IsCachingEnabled = false).CompileAssemblyFromFile("D:\scriptA.cs", info); dynamic script1 = CSScript.RoslynEvaluator .With(eval => eval.IsCachingEnabled = false).ReferenceAssembly(info.AssemblyFile).CompileMethod(@" using static script_a; Utils Test() { return new Utils(); }").CreateObject("*"); object utils = script1.Test(); //gives that error. image

AzizDZH commented 1 year ago

I understand my error when we use the instance of the assembly/class and it refers to the other assembly each of it should be loaded to appdomain context or a separate assembly context. So I've used separate assembly context loaded both dlls and it works fine var asmContxt = new UnloadableAssembly(); asmContxt.LoadFromAssemblyPath("AccountingScript.dll"); dynamic scriptInterf = asmContxt.LoadFromAssemblyPath("txPerson.dll") .CreateInstance("RootClass+TXPayment");

oleg-shilo commented 1 year ago

You can solve it by allowing the auto referencing of all appdomain assemblies. But it is not suitable for precise controlling over assembly probing. So I prefer disabling appdomain referencing and adding the asm references explicitly.

AzizDZH commented 1 year ago

Thanks for help. One question can we somehow change the name of the compiled modules instead of generated one "ℛ94128674-064b-4a19-bb52-27be4a47a9c8#1-0" ?

oleg-shilo commented 1 year ago

You cannot. As far as I know. It is Roslyn who selects the name.

AzizDZH commented 1 year ago

Actually there is an option in roslyn CSharpScript.Create(scriptText, scriptOptions).GetCompilation().WithAssemblyName(); it works fine

oleg-shilo commented 1 year ago

Your suggestion was just in time. I just published the new release v4.8.1.0.

You can set now CompileInfo.AssemblyName when you compile your script.