c# - 替换仅通过反射加载的程序集

标签 c# reflection plugins

在我当前正在进行的项目中,我们有许多类仅通过反射实例化,并且它们所属的程序集不会被任何其他类引用。

此方案允许在运行时替换程序集以扩展/纠正前一个程序集的功能。请注意,在我们的特定情况下,不可能使用 MarshalByRefObject,因此同一程序集的不同版本(公开具有相同名称但功能不同的类)最终会加载到同一个 AppDomain 中。

我提供一个极其简化的示例:考虑以下接口(interface)声明和控制台应用程序

public interface ISomeInterface
{
    string getData();
}

class Program
{
    static void Main(string[] args)
    {
        byte[] lastLibrary = null;
        Assembly lastAssembly = null;

        while (true)
        {
            byte[] theLibrary = File.ReadAllBytes("ClassLibrary1.dll");

            if (lastLibrary == null || !theLibrary.SequenceEqual(lastLibrary))
            {
                lastAssembly = Assembly.Load(theLibrary);
            }

            ISomeInterface obj = lastAssembly.CreateInstance("ClassLibrary1.Class1") as ISomeInterface;

            Console.WriteLine(obj.getData());

            lastLibrary = theLibrary;
            Thread.Sleep(1000);
        }
    }
}

以及以下接口(interface)实现(在单独的程序集上):

public class Class1 : ISomeInterface
{
    public string getData()
    {
        return "someText";
    }
}

正如预期的那样,如果我更改 ISomeInterface 的实现(例如,将“someText”更改为“someOtherText”)并用新的 dll 替换旧的 dll,则将使用最新版本。但我想知道:这种机制会给软件的稳定性带来问题的可能性有多大?我的意思是,在我仅通过反射实例化这些类并且没有其他组件引用它们之前,一切都是安全的吗?至于我们的初步测试,看起来一切正常,但我也想听听专家的意见。

我知道在这个特定的示例中,可以使用 MarshalByRefObject 来完成所有操作,但正如我之前所说,我们不可能朝这个方向前进。

最佳答案

这样的事情应该可以正常工作,但我认为您误解了实际发生的情况。

当您将程序集加载到 AppDomain 中时,只要该 AppDomin 存在,它就永远不会被释放。您要做的就是加载一个新的程序集。但这样做后,您不会发布旧版本。例如,如果先前版本的对象仍然存在,它将返回“someText”,即使新创建的对象将返回“someOtherText”。虽然这两个对象的类型名称都是 ClassLibrary1.Class1,但它们是不同的类型。

如果这种行为适合您,那么您应该没问题。但不要忘记,所有旧版本仍然会加载并保留在内存中,因此这样做实际上会导致内存泄漏。

关于c# - 替换仅通过反射加载的程序集,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6484430/

相关文章:

go - 通过反射将 *struct 归零(不知道底层类型)并将指针重新分配给接口(interface)

java - Eclipse插件: how to activate terminate button in Debug view

c# - 使用 Moq 验证委托(delegate)

c# - 将存储过程结果填充到 List<T>

python - 获取 'readable'格式的函数注释

C# 如何在参数数量相等时使用 System.Reflection 调用私有(private)重载方法

grails - Grails list-plugin-updates 命令中烦人的 SNAPSHOT 版本

javascript - 在设定时间禁用/启用色带

c# - Excel CSV 编码问题

c# - Entity Framework 6 添加外键