如何创建动态的程序集(C#)并动态加载实例程序集的依赖项?

时间:2014-04-02 22:46:09

标签: c# dynamic dependencies loading .net-assembly

我正在将 CalculatorDependency.dll 加载到 AppDomain ,这是添加类的依赖( IAdd 的实施来自 Calculator.dll Calculator.Interface.dll

问题是我不想把实施者dll( Calculator.dll )和它的依赖dll( CalculatorDependency.dll )放在执行装配位置或在GAC中执行。我想分别从给定位置动态加载它。所以我首先加载Interface实现者dll和它对AppDomain的依赖来创建一个实例。

这是我的代码!!

    static void Main(string[] args)
    {
        // Loading dependency dll into memory
        var dependency = string.Concat(Directory.GetCurrentDirectory(), @"\Implementations\CalculatorDependency.dll");
        var dependencyBytes = File.ReadAllBytes(dependency);

        // Loading implementer dll into memory
        var implementor = string.Concat(Directory.GetCurrentDirectory(), @"\Implementations\Calculator.dll");
        var implementorBytes = File.ReadAllBytes(implementor);

        // Adding dependency dll to AppDomain (CalculatorDependency.dll)
        AppDomain.CurrentDomain.Load(dependencyBytes);
        // Adding implementor dll to AppDomain (Calculator.dll)
        AppDomain.CurrentDomain.Load(implementorBytes);

        // Checking loaded assemblies and both above assemblies are exist in output
        var loadedAssemblies = AppDomain.CurrentDomain.GetAssemblies().ToList();
        foreach (var a in loadedAssemblies)
        {
            Console.WriteLine(a.GetName().Name);
        }

        // Calling function to get an instance of IAdd as Calculator.Add class from Calculator.dll
        var obj = GetObject<IAdd>();

        // Object was resolved successfully but was failed at this line as SumNew is a dependent function on CalculatorDependency.dll
        Console.WriteLine(obj.SumNew(2, 2));
    }

    public static T GetObject<T>()
    {
        var t = typeof(T);

        var objects = (
            from assembly in AppDomain.CurrentDomain.GetAssemblies()
            from type in assembly.GetExportedTypes()
            where typeof(T).IsAssignableFrom(type) && !type.FullName.Equals(t.FullName)
            select (T)Activator.CreateInstance(type)
        ).ToArray();

        return objects.FirstOrDefault();
    }

错误:

未处理的类型&#39; System.IO.FileNotFoundException&#39;发生在TestConsole.exe

其他信息:无法加载文件或程序集&#39; CalculatorDependency,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null&#39;或其中一个依赖项。系统找不到指定的文件。

已加载程序集的控制台输出:

enter image description here

有人可以帮我解决这里有什么问题吗?即使加载 CalculatorDependency.dll ,为什么它还在寻找要再次加载的文件?

2 个答案:

答案 0 :(得分:1)

最后我找到了解决问题的方法。

这对我有用。完美和我在寻找! :)

static void Main(string[] args)
{
    AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;

    var implementor = string.Concat(Directory.GetCurrentDirectory(), @"\Implementations\Calculator.dll");
    var implementorBytes = File.ReadAllBytes(implementor);

    AppDomain.CurrentDomain.Load(implementorBytes);

    Console.WriteLine(GetObject<IAdd>().SumNew(2, 2));
    Console.WriteLine(GetObject<IAdd>().SumNew(2, 5));
}

static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
{
    var dependencyResolverBaseDirectory = string.Concat(Directory.GetCurrentDirectory(), @"\Implementations");

    return Directory.GetFiles(dependencyResolverBaseDirectory, "*.dll")
        .Select(Assembly.LoadFile)
        .FirstOrDefault(assembly => string.Compare(args.Name, assembly.FullName, StringComparison.CurrentCultureIgnoreCase) == 0);
}

public static T GetObject<T>()
{
    var t = typeof(T);

    var objects = (
        from assembly in AppDomain.CurrentDomain.GetAssemblies()
        from type in assembly.GetExportedTypes()
        where typeof(T).IsAssignableFrom(type) && (string.Compare(type.FullName, t.FullName, StringComparison.CurrentCultureIgnoreCase) != 0)
        select (T)Activator.CreateInstance(type)
    ).ToList();

    return objects.FirstOrDefault();
}

答案 1 :(得分:0)

如何在“内存流”中加载文件然后使用它。          使用(FileStream文件=新FileStream(@“ c:\ temp \ TestAccountScrubbing.dll”,FileMode.Open,FileAccess.Read))             {                 byte [] bytes =新的byte [file.Length];                 file.Read(bytes,0,(int)file.Length);                 ms.Write(bytes,0,(int)file.Length);             }             ms.Seek(0,SeekOrigin.Begin);             程序集程序集= Assembly.Load(ms.ToArray());

        Type type = assembly.GetType("TestAccountScrubbing.AccountScubbing");
        object obj = Activator.CreateInstance(type);
        var returnValue =type.InvokeMember("Main",
            BindingFlags.Default | BindingFlags.InvokeMethod,
            null,
            obj,
            new object[] { "Hello World" });
        }