1

Previously I was using this call to load all cs file that extends from Rule class

var repository = new RuleRepository();
repository.Load(x => x.From(typeof(Rule1).Assembly));

By calling Load method as shown above all the class files of the same type as Rule1.cs (meaning all files extending from Rule class) get loaded into repository memory. Currently I have decided to convert all these .cs files (i.e. Rule1.cs) into dlls and scan the folder containing these dlls. How can I achieve this behavior? Currently I am doing something like this

Assembly assembly1 = Assembly.LoadFile(Server.MapPath("Rule1.dll"));
List<Assembly> asmblyList = new List<Assembly>();
asmblyList.Add(assembly1);
repository.Load(x => x.From(asmblyList));

I want to scan all the assemblies of type Rule1.dll from the folder. How can I possibly do it? Any help would be great.

talaa123
  • 123
  • 1
  • 2
  • 14
  • 1
    http://stackoverflow.com/a/20771713/4498937 maybe this will help? – terbubbs Jan 18 '16 at 16:40
  • @terbubbs The link you posted is on how to load referenced assemblies within an assembly. Whereas my question is to load all the assemblies located in one folder without knowing there name. Let me put it this way, I have only the path to the folder and not the names of the dlls. How can I load all the dlls from that folder into some list etc. – talaa123 Jan 18 '16 at 16:57
  • i see what you're saying. let me look into that – terbubbs Jan 18 '16 at 17:09
  • so the DLLs that you're loading has to be type `Rule1`? – terbubbs Jan 18 '16 at 17:11
  • for loading the DLLs from folder, i would think you can use this solution http://stackoverflow.com/a/5599581/4498937 – terbubbs Jan 18 '16 at 17:14
  • @terbubbs Thank it works. But, can I somehow make sure that all the assemblies that I'm loading are of type Rule1.dll (Extended from Rule class)? So if I have 15 dlls in that folder and 13 are of type Rule1.dll (meaning that these 13 are extended from the same Rule parent class) whereas other 2 dlls are some random ones. Can I somehow load all 15 and then drop these 2 odd ones out? – talaa123 Jan 18 '16 at 17:34
  • can you try `assembly1.GetType().IsSubclassOf(Rule1)`? – terbubbs Jan 18 '16 at 17:43

1 Answers1

1

As in the comments mentioned, get a list of files and load them is not a problem, but there is only one way to drop a loaded assembly out and this is to unload the whole AppDomain. Have a look at this example:

static void Main(string[] args)
{
    var path = AssemblyDirectory + @"\external\";
    var files = Directory.GetFiles(path); //get all files

    var ad = AppDomain.CreateDomain("ProbingDomain"); //create another AppDomain
    var tunnel = (AppDomainTunnel)
        ad.CreateInstanceAndUnwrap(typeof (AppDomainTunnel).Assembly.FullName,
        typeof (AppDomainTunnel).FullName); //create tunnel

    var valid = tunnel.GetValidFiles(files); //pass file paths, get valid ones back
    foreach (var file in valid)
    {
        var asm = Assembly.LoadFile(file); //load valid assembly into the main AppDomain
        //do something
    }

    AppDomain.Unload(ad); //unload probing AppDomain
}

private class AppDomainTunnel : MarshalByRefObject 
{   
    public string[] GetValidFiles(string[] files) //this will run in the probing AppDomain
    {
        var valid = new List<string>();
        foreach (var file in files)
        {
            try
            {   //try to load and search for valid types
                var asm = Assembly.LoadFile(file);
                if (asm.GetTypes().Any(x => x.IsSubclassOf(typeof (Rule1))))
                    valid.Add(file); //valid assembly found
            }
            catch (Exception)
            {
                //ignore unloadable files (non .Net, etc.)
            }
        }
        return valid.ToArray();
    }
}
//found here: http://stackoverflow.com/a/283917/4035472
public static string AssemblyDirectory
{
    get
    {
        string codeBase = Assembly.GetExecutingAssembly().CodeBase;
        UriBuilder uri = new UriBuilder(codeBase);
        string path = Uri.UnescapeDataString(uri.Path);
        return Path.GetDirectoryName(path);
    }
}
thehennyy
  • 4,020
  • 1
  • 22
  • 31