Are there reference implementations of hot-swapping in .NET?
Asked Answered
C

1

6

I'm looking for a good implementation of hot-swapping done in .NET. The things I need are:

  • Being able to deploy DLLs in a particular folder and have a running system pick them up.
  • Having the running system update corresponding references in the container.

I've been looking into MEF and its directory loading mechanism, but it seems very unreliable. Maybe someone out there has an alternative implementation?

Cleptomania answered 5/3, 2013 at 19:15 Comment(8)
Why do you think MEF is unreliable? What else have you looked at? A design question like this might do better at Software Engineering, but you will need to provide more details and show what you've considered.Glandule
How hot swappable do you want it to be? Should you be able to replace an existing assembly while the old one is in use?Unmarked
How much performance you are willing to pay for the feature? Crossing AppDomain boundary is not cheap (and it is the only way in .Net to isolate DLL with the same identity)... Does IIS model (reset AppDomain on change of binaries/config) work for you?Pointing
Have a look at .NET Framework's Shadow Copy combined with MEF's DirectoryCatalog and the Recomposition feature. A quick prototype can be based on this Q&A https://mcmap.net/q/1168600/-facing-error-during-catalog-refresh-the-new-dll-is-not-used/850119Fireproof
@AlbinSunnanbo no, replacing an assembly is impossible; also you cannot unload an assemblyCleptomania
@AlexeiLevenkov I don't need to unload anything, only add new versionsCleptomania
@Verdolino umm, no, I don't want to reload the assemblies manually. having a manual reload mechanism is very easy. I want something that not only reloads automatically on new DLLs being added, but also propagates dependenciesCleptomania
@DmitriNesteruk hopefully you have solved this in the past three yearsForbore
F
6

You can provide a custom event handler for AssemblyResolve by calling newAppDomain() below. Supply your directory so AppDomain looks there. When loading a Type, use function loadFromAppDomain() to return it. This should allow you to copy new dlls to C:\dlls at runtime and reload from there. (Forgive me, I translated this from my VB source to C# according to your tag.)

String dllFolder = "C:\\dlls";

public void newAppDomain()
{
    AppDomain.CurrentDomain.AssemblyResolve += new ResolveEventHandler(assemblyResolve);
}

private static Assembly assemblyResolve(Object sender, ResolveEventArgs args){
    String assemblyPath = Path.Combine(dllFolder, new AssemblyName(args.Name).Name + ".dll");
    if(!File.Exists(assemblyPath))
    {
        return null;
    }
    else
    {
        return Assembly.LoadFrom(assemblyPath);
    }
}

private Type loadFromAppDomain(String className)
{
    Assembly[] asses = AppDomain.CurrentDomain.GetAssemblies();
    List<Type> types = new List<Type>();
    foreach(Assembly ass in asses)
    {
        Type t = ass.GetType(className);
        if(t != null) types.Add(t);
    }
    if(types.Count == 1)
        return types.First();
    else
        return null;
}
Forbore answered 5/3, 2013 at 19:51 Comment(3)
+1 for thorough answer. This is how Microsoft intends for you to hot-swap.Contiguity
+1.This approach obviously works only for strongly typed, correctly versioned assemblies. @evanmcdonnal, side note - please never shorten assembly to 3 letters... looks fun till you need to ask someone to read your code, especially someone with not so advanced sense of humor.Pointing
@Alexei I hope we all have good senses of humor. I agree about the strongly typed, versioned assemblies. OP did not go into this detail, but the approach works well in my environment.Forbore

© 2022 - 2024 — McMap. All rights reserved.