我们的测试机器上有个很奇怪的bug。错误是:

系统。来自程序集“activeviewer(…)”的类型“DummyItem”中的方法“SetShort”没有实现。

我就是不明白为什么。SetShort在DummyItem类中,我甚至重新编译了一个版本,写入事件日志,只是为了确保它不是部署/版本控制问题。奇怪的是,调用代码甚至不调用SetShort方法。


当前回答

当我之前在一个程序集的单元测试期间启用了代码覆盖时,我也得到了这个错误。由于某种原因,Visual Studio“缓冲”了这个特定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>()...

当我的应用程序没有对另一个程序集的引用时,我得到了这个,该程序集定义了错误消息中的方法使用的类。运行PEVerify会给出更有用的错误:“系统无法找到指定的文件。”

对我来说,解决方案与实现接口的项目设置了“Register for COM Interop”属性有关。取消勾选这个选项为我解决了这个问题。

我在WCF服务中得到了这个,因为选择了x86构建类型,导致箱子在bin\x86下而不是bin下。选择Any CPU会导致重新编译的dll到达正确的位置(我不会详细说明这是如何发生的)。

另一种可能是在依赖关系中混合发布和调试构建。例如,程序集A依赖于程序集B, A是在调试模式下构建的,而GAC中的B副本是在发布模式下构建的,反之亦然。