Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to prevent smart loading of DLL in .NET?

Tags:

c#

.net

dll

I have some issue with a program I'm working on. It's composed of 2 DLLs, with dll A referencing dll B. Dll A contains one public method, in which first action (before instanciating any class in B) is to check some network location to see if a new version of dll B is available. If so, it downloads it at the same location of current B, which should not be a problem since nothing from B is instanciated. Sadly, it is instanciated and so I get an error it is already referenced by the process that owns A and cannot be replaced.

Do you have any idea of the reason why it is already referenced, and if there is any solution to avoid this?

public class L10nReports//Class in DLL A
{
    public L10nReports() //constructor
    {
    }

    //only public method is this class
    public string Supervise(object projectGroup, out string msg)
    {
        //Checks for updates of dll B and downloads it if available. And fails.
        manageUpdate();

        //first instanciation of any class from dll B
        ReportEngine.ReportEngine engine = new ReportEngine.ReportEngine();

        string result = engine.Supervise(projectGroup, out msg);

        return result;
    }
like image 276
Antoine Avatar asked Dec 21 '22 16:12

Antoine


2 Answers

By the time your "Supervise" method is JITted, the B dll will be loaded. THe issue here is that the DLL is loaded the first time type information for some type in B.dll is needed, not the first time an object is instantiated.

So you must check for update before you reference any type in B.dll, and before you call any methods that use a type in B.dll.

public class L10nReports//Class in DLL A
{
    public L10nReports() //constructor
    {
    }


    //only public method is this class
    public string Supervise(object projectGroup, out string msg)
    {
       manageUpdate();
       return SuperviseImpl(projectGroup, out msg);
    }


    private string SuperviseImpl(object projectGroup, out string msg)
    {
        //first instanciation of any class from dll B
        ReportEngine.ReportEngine engine = new ReportEngine.ReportEngine();

        string result = engine.Supervise(projectGroup, out msg);

        return result;
    }
like image 100
Philip Rieck Avatar answered Jan 04 '23 15:01

Philip Rieck


The Jit compiler needs to load Dll B, in order to check/validate the Supervise method.

Move calls to Dll B into another method, and prevent this method from being inlined ([MethodImpl(MethodImplOptions.NoInlining)]). Otherwise you might have strange effects switching from Debug to Release mode.

If I remember it correctly, inlining is not used for Debug compiled code, but release code might inline the called method, making the jitter load Dll B before the check.

    //only public method is this class
    // all calls to dll B must go in helper function
    public string Supervise(object projectGroup, out string msg)
    {
        //Checks for updates of dll B and downloads it if available. And fails.
        manageUpdate();

        return SuperviseHelper(projectGroup, out msg);
    }

    [MethodImpl(MethodImplOptions.NoInlining)]
    public string SuperviseHelper(object projectGroup, out string msg) {
        //first instanciation of any class from dll B
        ReportEngine.ReportEngine engine = new ReportEngine.ReportEngine();

        string result = engine.Supervise(projectGroup, out msg);

        return result;
    }
like image 31
GvS Avatar answered Jan 04 '23 13:01

GvS