gpt4 book ai didi

c# - Mono 无法将 Type 转换为 Type A

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:01:30 25 4
gpt4 key购买 nike

我正在使用 C# 创建一个插件框架。该框架的主要需求是在运行时加载、卸载和更新插件。

为了完成这个,我一直在创建 AppDomains 并将插件程序集加载到 AppDomains 中。

在 Windows 上的 Microsoft .NET 上一切正常,但插件在 mac 或 linux 上运行的单声道上不起作用。

尝试启动插件时出现如下异常:

无法转换类型为“System.Func”1 的参数 0 [[API.Network.NodeType、API、Version=1.0.0.0、Culture=neutral、PublicKeyToken=null]]、mscorlib、Version=4.0.0.0、Culture =neutral, PublicKeyToken=b77a5c561934e089' 键入 'System.Func`1[[API.Network.NodeType, API, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null]], mscorlib, Version=4.0.0.0, Culture =中性,PublicKeyToken=b77a5c561934e089'

这是因为每个插件都有自己的 API.dll 程序集副本,尽管程序集是相同的副本,但 mono 认为类型不同。

如何让插件从主应用程序的目录加载 API.dll?或者,我怎样才能让单声道将类型视为相同?

最佳答案

好吧,为了找到你问题的答案,我创建了一个简单的插件系统,并在 Windows 下成功地在 mono 3.2.3 上测试了它(不幸的是,我现在不能在 Linux 上进行测试,也许明天)。我的代码:

SDK.dll

using System;

namespace SDK
{
public interface IPlugin
{
void SomeMethod();

SomeSDKType GetSDKType();

}
}

using System;
using System.Collections.Generic;

namespace SDK
{
[Serializable]
public class StringEventArgs : EventArgs
{

public string Message { get; set; }

}

public class SomeSDKType : MarshalByRefObject
{

public event EventHandler<StringEventArgs> SDKEvent;

public Action SDKDelegate;

public void RiseSDKEvent(string message)
{
var handler = SDKEvent;
if (handler != null) SDKEvent(this, new StringEventArgs { Message = message });
}

public Dictionary<int, string> GetDictionary()
{
var dict = new Dictionary<int, string> ();
dict.Add(1, "One");
dict.Add(2, "Two");
return dict;
}

}
}

Plugin.dll

using System;
using SDK;

namespace Plugin
{
public class Plugin : MarshalByRefObject, IPlugin
{
public Plugin()
{
}

public void SomeMethod()
{
Console.WriteLine("SomeMethod");
}

public SomeSDKType GetSDKType()
{
var obj = new SomeSDKType();
obj.SDKDelegate = () => Console.WriteLine("Delegate called from {0}", AppDomain.CurrentDomain.FriendlyName);
return obj;
}
}
}

托管程序

using System;
using System.Reflection;
using System.IO;
using SDK;

namespace AppDomains
{
class MainClass
{
public static void Main(string[] args)
{
var domain = AppDomain.CreateDomain("Plugin domain"); // Domain for plugins
domain.Load(typeof(IPlugin).Assembly.FullName); // Load assembly containing plugin interface to domain

var currentPath = Directory.GetCurrentDirectory();
var pluginPath = Path.Combine(currentPath, "Plugins");
var pluginFiles = Directory.GetFiles(pluginPath, "*.dll");
foreach (var pluginFile in pluginFiles) // Foreach dll in Plugins directory
{
var asm = Assembly.LoadFrom(pluginFile);
foreach (var exportedType in asm.GetExportedTypes())
{
if (!typeof(IPlugin).IsAssignableFrom(exportedType)) continue; // Check if exportedType implement IPlugin interface
domain.Load(asm.FullName); // If so load this dll into domain
var plugin = (IPlugin)domain.CreateInstanceAndUnwrap(asm.FullName, exportedType.FullName); // Create plugin instance
plugin.SomeMethod(); // Call plugins methods
var obj = plugin.GetSDKType();
obj.SDKDelegate();
var dict = obj.GetDictionary();
foreach (var pair in dict)
{
Console.WriteLine("{0} - {1}", pair.Key, pair.Value);
}
obj.SDKEvent += obj_SDKEvent;
obj.RiseSDKEvent(string.Format("Argument from domain {0}", AppDomain.CurrentDomain.FriendlyName));
}
}
Console.ReadLine();
}

static void obj_SDKEvent(object sender, StringEventArgs e)
{
Console.WriteLine("Received event in {0}", AppDomain.CurrentDomain.FriendlyName);
Console.WriteLine(e.Message);
}
}
}

App.config

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<probing privatePath="Plugins"/>
</assemblyBinding>
</runtime>
</configuration>

对代码的一些解释。我用插件接口(interface)创建了 SDK dll。所有插件和主机应用程序都必须引用它。插件必须在没有 SDK dll 的情况下提供,因为主机应用程序已经包含它。它们放入主机应用程序目录中的 Plugins 目录(即,如果应用程序路径 = c:\MyApp,则插件位于 c:\MyApp\Plugins) 因此,为了提供 CLR(或单声道)查找插件组件的机会,我还创建了带有探测元素的 App.config 文件。

希望这对您有所帮助。

关于c# - Mono 无法将 Type 转换为 Type A,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19570371/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com