我正在开发一个需要允许 3rd-party 插件的项目。我以前使用过插件,但从来没有遇到过问题。
我确定我的问题是因为 WPF 不喜欢我使用 Assembly.LoadFile(file) 和 Activator.CreateInstance(t)!
我遇到的错误是:
The component 'Servus.Forms.MainWindow' does not have a resource identified by the URI '/Servus;component/forms/mainwindow.xaml'.
这显示在我的 MainForm 构造函数中: InitializeComponent();
如果我在加载 MainForm 后加载插件,它会毫无问题地加载,但是当打开任何其他表单(我的应用程序中有很多)时,我会遇到与 about 相同的问题,但该特定表单会出现相关错误。
我也尝试在自己的 AppDomain 中加载插件,如下所示:
PluginDomain temp = new PluginDomain();
PluginBase tempPlug = temp.GetPlugin(file);
有以下课程:
public class PluginDomain
{
    public AppDomain CurrentDomain { get; set; }
    public ServusAssemblyLoader CurrentAssemblyLoader { get; set; }
    private readonly Random _rand = new Random();
    public PluginDomain()
    {
    }
    public PluginBase GetPlugin(string assemblyName)
    {
        try
        {
            string appBase = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
            var ads = new AppDomainSetup { ApplicationBase = appBase, PrivateBinPath = appBase, ShadowCopyFiles = "true" };
            CurrentDomain = AppDomain.CreateDomain("ServusDomain_Plugin_" + _rand.Next(0, 100000), null, ads);
            AppDomain.CurrentDomain.AssemblyResolve += CurrentDomain_AssemblyResolve;
            CurrentAssemblyLoader = (ServusAssemblyLoader)
            CurrentDomain.CreateInstanceAndUnwrap(Assembly.GetExecutingAssembly().FullName, typeof(ServusAssemblyLoader).FullName);
            AppDomain.CurrentDomain.AssemblyResolve -= CurrentDomain_AssemblyResolve;
            return CurrentAssemblyLoader.Load(assemblyName);
        }
        catch (Exception e)
        {
            CConsole.WriteLine("Error: " + e.Message);
        }
        finally
        {
            CurrentAssemblyLoader = null;
            AppDomain.Unload(CurrentDomain);
        }
        return null;
    }
    static Assembly CurrentDomain_AssemblyResolve(object sender, ResolveEventArgs args)
    {
        string[] parts = args.Name.Split(',');
        string file = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) + "\\" + parts[0].Trim() + ".dll";
        return Assembly.LoadFrom(file);
    }
}
public class ServusAssemblyLoader : MarshalByRefObject, IAssemblyLoader
{
    public PluginBase Load(string file)
    {
        Assembly asm = Assembly.LoadFrom(file);
        foreach (Type t in asm.GetTypes())
        {
            if (t.IsSubclassOf(typeof(PluginBase)))
            {
                return (PluginBase)Activator.CreateInstance(t);
            }
        }
        return null;
    }
}
public interface IAssemblyLoader
{
    PluginBase Load(string file);
}
这将返回一个透明代理对象,如下所示:
{System.Runtime.Remoting.Proxies.__TransparentProxy}
但是我不确定如何使用它,因为我希望它返回一个 PluginBase 对象。
我读过很多人也有这个问题,他们的答案说要使用新的 AppDomain,但正如你所看到的,这对我现在没有帮助。
我希望我已经为您提供了足够的信息,有人可以帮忙吗?