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

问题描述 投票:0回答:2

我正在将CalculatorDependency.dll加载到AppDomain,它是Calculator.dll的Add类(来自Calculator.Interface.dll的IAdd实现)的依赖项。

问题是我不想在执行程序集位置或GAC中放置实现者DLL(Calculator.dll)和它的依赖dll(CalculatorDependency.dll)。我想分别从给定位置动态加载它。所以我正在加载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();
    }

错误:

TestConsole.exe中发生了未处理的“System.IO.FileNotFoundException”类型异常

附加信息:无法加载文件或程序集“CalculatorDependency,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null”或其依赖项之一。该系统找不到指定的文件。

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

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

c# dynamic dependencies loading .net-assembly
2个回答
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();
}

0
投票

如何在内存流中加载文件然后使用它。 using(FileStream file = new FileStream(@“c:\ temp \ TestAccountScrubbing.dll”,FileMode.Open,FileAccess.Read)){byte [] bytes = new byte [file.Length]; file.Read(bytes,0,(int)file.Length); ms.Write(bytes,0,(int)file.Length); } ms.Seek(0,SeekOrigin.Begin); Assembly assembly = 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" });
        }
© www.soinside.com 2019 - 2024. All rights reserved.