我们的测试机器上有个很奇怪的bug。错误是:
系统。来自程序集“activeviewer(…)”的类型“DummyItem”中的方法“SetShort”没有实现。
我就是不明白为什么。SetShort在DummyItem类中,我甚至重新编译了一个版本,写入事件日志,只是为了确保它不是部署/版本控制问题。奇怪的是,调用代码甚至不调用SetShort方法。
我们的测试机器上有个很奇怪的bug。错误是:
系统。来自程序集“activeviewer(…)”的类型“DummyItem”中的方法“SetShort”没有实现。
我就是不明白为什么。SetShort在DummyItem类中,我甚至重新编译了一个版本,写入事件日志,只是为了确保它不是部署/版本控制问题。奇怪的是,调用代码甚至不调用SetShort方法。
当前回答
I had the same problem. I figured out that my assembly, which is loaded by the main program, had some references with "Copy Local" set to true. These local copies of references were looking for other references in the same folder, which did not exist because the "Copy Local" of other references was set to false. After the deletion of the "accidentally" copied references the error was gone because the main program was set to look for correct locations of references. Apparently the local copies of the references screwed up the sequence of calling because these local copies were used instead of the original ones present in the main program.
重要的信息是,出现此错误是因为缺少加载所需程序集的链接。
其他回答
我在使用Autofac和大量动态程序集加载时遇到了这个错误。
在执行Autofac解析操作时,运行库将无法加载其中一个程序集。错误消息抱怨程序集'ImplementationAssembly'中的'MyType'类型的方法'MyMethod'没有实现。在Windows Server 2012 R2虚拟机上运行时出现问题,但在Windows 10或Windows Server 2016虚拟机上没有出现问题。
ImplementationAssembly引用System.Collections.Immutable 1.1.37,并包含IMyInterface<T1,T2>接口的实现,该接口在单独的definentationassembly中定义。defintionassembly引用System.Collections.Immutable 1.1.36。
“未实现”的IMyInterface<T1,T2>中的方法具有类型为IImmutableDictionary<TKey, TRow>的参数,该参数在System.Collections.Immutable中定义。
在程序目录中找到的System.Collections.Immutable的实际副本是版本1.1.37。在我的Windows Server 2012 R2虚拟机上,GAC包含System.Collections.Immutable 1.1.36的副本。在Windows 10和Windows Server 2016上,GAC包含System.Collections.Immutable 1.1.37的副本。只有当GAC包含较旧版本的DLL时,才会发生加载错误。
因此,程序集加载失败的根本原因是对System.Collections.Immutable的引用不匹配。接口定义和实现具有看起来相同的方法签名,但实际上依赖于不同版本的System.Collections。不可变,这意味着运行时不考虑实现类与接口定义匹配。
添加以下绑定重定向到我的应用程序配置文件修复了这个问题:
<dependentAssembly>
<assemblyIdentity name="System.Collections.Immutable" publicKeyToken="b03f5f7f11d50a3a" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-1.1.37.0" newVersion="1.1.37.0" />
</dependentAssembly>
在我的例子中,它帮助重置WinForms工具箱。
当在设计器中打开窗体时,我得到了异常;然而,编译和运行代码是可能的,并且代码的行为符合预期。异常发生在实现我引用的库之一的接口的本地UserControl中。更新此库后出现错误。
这个UserControl列在WinForms工具箱中。可能Visual Studio保留了库的一个过时版本的引用,或者在某个地方缓存了一个过时的版本。
下面是我如何从这种情况中恢复过来的:
右键单击WinForms工具箱,然后单击上下文菜单中的重置工具箱。(这将从工具箱中删除自定义项)。 在我的例子中,“工具箱”项被恢复到默认状态;但是,“工具箱”中缺少指针箭头。 关闭Visual Studio。 在我的案例中,Visual Studio以一个违反异常终止并中止。 重新启动Visual Studio。 现在一切都很顺利。
I had the same problem. I figured out that my assembly, which is loaded by the main program, had some references with "Copy Local" set to true. These local copies of references were looking for other references in the same folder, which did not exist because the "Copy Local" of other references was set to false. After the deletion of the "accidentally" copied references the error was gone because the main program was set to look for correct locations of references. Apparently the local copies of the references screwed up the sequence of calling because these local copies were used instead of the original ones present in the main program.
重要的信息是,出现此错误是因为缺少加载所需程序集的链接。
这仅仅意味着实现项目在我的案例中已经过时了。重新构建了包含接口的DLL,但实现DLL陈旧。
当我尝试在dot net 5中使用自定义的AssemblyLoadContext(没有AppDomain创建)和共享类型(你需要使用它来调用插件方法而没有反射)实现插件程序集加载时,我得到了这个问题。这篇文章对我没有任何帮助。以下是我解决这个问题的方法:
为了允许调试插件加载没有问题-设置项目输出路径到主机应用程序bin文件夹。您将调试插件项目构建后得到的相同程序集。这可能是临时更改(仅用于调试)。 要修复TypeLoadException异常,你需要将所有“契约程序集”引用的程序集加载为共享程序集(运行时程序集除外)。检查加载器上下文实现(在构造函数中加载sharedAssemblies):
public class PluginAssemblyLoadContext : AssemblyLoadContext
{
private AssemblyDependencyResolver _resolver;
private IDictionary<string, Assembly> _loadedAssemblies;
private IDictionary<string, Assembly> _sharedAssemblies;
private AssemblyLoadContext DefaultAlc;
private string _path;
public PluginAssemblyLoadContext(string path, bool isCollectible, params Type[] sharedTypes)
: this(path, isCollectible, sharedTypes.Select(t => t.Assembly).ToArray())
{
}
public PluginAssemblyLoadContext(string path, bool isCollectible, params Assembly[] sharedAssemblies)
: base(isCollectible: isCollectible)
{
_path = path;
DefaultAlc = GetLoadContext(Assembly.GetExecutingAssembly()) ?? Default;
var fileInfo = new FileInfo(_path);
if (fileInfo.Exists)
{
_resolver = new AssemblyDependencyResolver(_path);
_sharedAssemblies = new Dictionary<string, Assembly>(StringComparer.OrdinalIgnoreCase);
foreach (var a in sharedAssemblies.Distinct())
{
LoadReferencedAssemblies(a);
}
_loadedAssemblies = new Dictionary<string, Assembly>();
var assembly = LoadFromAssemblyPath(fileInfo.FullName);
_loadedAssemblies.Add(fileInfo.FullName, assembly);
}
else
{
throw new FileNotFoundException($"File does not exist: {_path}");
}
}
public bool LoadReferencedAssemblies(Assembly assembly)
{
if (assembly == null)
{
throw new ArgumentNullException(nameof(assembly));
}
if (string.IsNullOrEmpty(assembly.Location))
{
throw new NotSupportedException($"Assembly location is empty string or null: {assembly.FullName}");
}
var alc = GetLoadContext(assembly);
if (alc == this)
{
throw new InvalidOperationException($"Circular assembly loader dependency detected");
}
if (!_sharedAssemblies.ContainsKey(assembly.Location))
{
_sharedAssemblies.Add(assembly.Location, assembly);
foreach (var an in assembly.GetReferencedAssemblies())
{
var ra = alc.LoadFromAssemblyName(an);
LoadReferencedAssemblies(ra);
}
return true;
}
else
{
return false;
}
}
public IEnumerable<Type> GetCommandTypes<T>()
{
var cmdType = typeof(T);
return _loadedAssemblies.Values.SelectMany(a => a.GetTypes()).Where(t => cmdType.IsAssignableFrom(t));
}
public IEnumerable<T> CreateCommands<T>(Assembly assembly)
{
foreach (var cmdType in GetCommandTypes<T>())
{
yield return (T)Activator.CreateInstance(cmdType);
}
}
protected override Assembly Load(AssemblyName assemblyName)
{
var path = _resolver.ResolveAssemblyToPath(assemblyName);
if (path != null)
{
if (_sharedAssemblies.ContainsKey(path))
{
return _sharedAssemblies[path];
}
if (_loadedAssemblies.ContainsKey(path))
{
return _loadedAssemblies[path];
}
return LoadFromAssemblyPath(path);
}
return DefaultAlc.LoadFromAssemblyName(assemblyName);
}
}
用法:
var loader = new PluginAssemblyLoadContext(fullPath, false, typeof(IPluginCommand));
loader.CreateCommands<IPluginCommand>()...