sourcecode

TypeLoadException에 ' 구현 없음'이라고 표시되지만 구현됩니다.

codebag 2023. 5. 3. 21:24
반응형

TypeLoadException에 ' 구현 없음'이라고 표시되지만 구현됩니다.

우리 시험기에 아주 이상한 버그가 있어요.오류:

System.TypeLoadException: Method 'SetShort' in type 'DummyItem' from assembly 'ActiveViewers (...)' does not have an implementation.

왜 그런지 이해할 수가 없어요. SetShort에 ?DummyItem배포/버전 문제가 아닌지 확인하기 위해 이벤트 로그에 기록된 버전을 다시 컴파일했습니다.이상한 것은 호출 코드가 전화도 하지 않는다는 것입니다.SetShort방법.

참고 - 이 답변이 도움이 되지 않는 경우, 시간을 내어 사람들이 추가한 다른 답변을 아래로 스크롤하십시오.

단답형

메소드를 한 어셈블리의 인터페이스에 추가한 다음 다른 어셈블리의 구현 클래스에 추가할 때 인터페이스 어셈블리의 새 버전을 참조하지 않고 구현 어셈블리를 재구성하는 경우에 이러한 문제가 발생할 수 있습니다.

이 경우 DummyItem은 다른 어셈블리의 인터페이스를 구현합니다.SetShort 메서드는 최근에 인터페이스와 DummyItem 모두에 추가되었지만 DummyItem을 포함하는 어셈블리는 이전 버전의 인터페이스 어셈블리를 참조하여 다시 작성되었습니다.그래서 SetShort 방법은 효과적으로 존재하지만, 마법의 소스가 인터페이스의 동등한 방법과 연결하지 않습니다.

긴 대답

이를 복제하려면 다음을 수행하십시오.

  1. 클래스 라이브러리 프로젝트 만들기:InterfaceDef에서 클래스를 하나만 추가하고 다음을 빌드합니다.

    public interface IInterface
    {
        string GetString(string key);
        //short GetShort(string key);
    }
    
  2. 두 번째 클래스 라이브러리 프로젝트를 만듭니다.구현(별도 솔루션 포함), InterfaceDef.dll을 프로젝트 디렉토리에 복사하여 파일 참조로 추가하고 클래스 하나만 추가한 후 다음을 빌드합니다.

    public class ImplementingClass : IInterface
    {
        #region IInterface Members
        public string GetString(string key)
        {
            return "hello world";
        }
    
        //public short GetShort(string key)
        //{
        //    return 1;
        //}
        #endregion
    }
    
  3. 세 번째 콘솔 프로젝트 만들기:클라이언트 코드를 사용하여 두 dll을 프로젝트 디렉터리에 복사하고 파일 참조를 추가한 다음 주 메서드에 다음 코드를 추가합니다.

     IInterface test = new ImplementingClass();
     string s = test.GetString("dummykey");
     Console.WriteLine(s);
     Console.ReadKey();
    
  4. 코드를 한 번 실행하면 콘솔에 "hello world"라고 표시됩니다.

  5. 두 dll 프로젝트의 코드 주석을 제거하고 다시 빌드합니다. 두 dll을 다시 클라이언트 코드 프로젝트로 복사하고 다시 빌드한 후 다시 실행하십시오.TypeLoadException은 ImplementingClass를 인스턴스화할 때 발생합니다.

질문자 자신의 답변이 이미 언급한 내용 외에도 다음 사항에 유의할 필요가 있습니다.클래스가 인터페이스 메서드와 동일한 서명을 가진 메서드를 구현하지 않고도 해당 메서드를 가질 수 있기 때문입니다.다음 코드는 이를 보여줍니다.

public interface IFoo
{
    void DoFoo();
}

public class Foo : IFoo
{
    public void DoFoo() { Console.WriteLine("This is _not_ the interface method."); }
    void IFoo.DoFoo() { Console.WriteLine("This _is_ the interface method."); }
}

Foo foo = new Foo();
foo.DoFoo();               // This calls the non-interface method
IFoo foo2 = foo;
foo2.DoFoo();              // This calls the interface method

오류 메시지의 메서드가 사용하는 클래스를 정의하는 다른 어셈블리에 대한 참조가 응용 프로그램에 없을 때 이 메시지가 표시되었습니다.PEVerify를 실행하면 "시스템에서 지정한 파일을 찾을 수 없습니다."라는 더 유용한 오류가 발생했습니다.

저는 같은 메시지를 발견했고 우리가 발견한 것은 다음과 같습니다.우리는 프로젝트에서 제3자 dll을 사용합니다.새로운 릴리스가 나온 후에 우리는 프로젝트를 변경하여 새로운 dll 세트를 가리키고 성공적으로 컴파일했습니다.

런타임 중에 인터페이스된 클래스 중 하나를 인스턴스화하려고 할 때 예외가 발생했습니다.우리는 다른 모든 참조가 최신인지 확인했지만 여전히 운이 없습니다.오류 메시지에 포함된 메서드의 반환 유형이 참조되지 않은 새 어셈블리에서 완전히 새로운 유형임을 (오브젝트 브라우저를 사용하여) 발견하는 데 시간이 좀 걸렸습니다.

우리는 어셈블리에 참조를 추가했고 오류가 사라졌습니다.

  • 오류 메시지는 상당히 오해의 소지가 있지만 어느 정도 올바른 방향(올바른 방법, 잘못된 메시지)을 가리켰습니다.
  • 문제의 방법을 사용하지 않았는데도 예외가 발생했습니다.
  • 그래서 다음과 같은 질문이 나옵니다.어떤 경우에도 이 예외가 발생하면 컴파일러가 이 예외를 선택하지 않는 이유는 무엇입니까?

저는 다음 시나리오에서 이 오류를 받았습니다.

  • 어셈블리 A와 B 모두 시스템을 참조했습니다.Web.MVC 버전 3.0.0.0
  • 어셈블리 A는 어셈블리 B를 참조하고 시스템에서 클래스를 반환하는 메서드를 사용하여 어셈블리 B의 인터페이스를 구현하는 클래스를 가지고 있습니다.웹.MVC.
  • 어셈블리 A이(가) 시스템으로 업그레이드되었습니다.Web.MVC 버전 4.0.0.0
  • 어셈블리 C는 아래의 코드를 실행했습니다(FertPin).반.연락처가 어셈블리 A에 포함됨):

var target = Assembly.GetAssembly(typeof(FertPin.Classes.Contact));

저의 해결책은 시스템을 업그레이드하는 것이었습니다.어셈블리 B의 4.0.0.0에 대한 Web.MVC 참조.이제 명백해 보입니다!

오리지널 포스터 덕분에!

서명된 어셈블리의 버전이 올바르지 않은 경우에도 이 오류가 발생할 수 있습니다.이 원인에 대한 정상적인 증상은 아니지만, 여기 제가 걸린 시나리오가 있습니다.

  • asp.net 프로젝트에는 어셈블리 A와 어셈블리 B가 포함되어 있습니다. B는 강력한 이름을 가지고 있습니다.

  • 어셈블리 A에서 활성화기를 사용합니다.어셈블리 C를 로드하기 위한 인스턴스(instance) 생성(즉, 별도로 빌드된 C에 대한 참조가 없음)

  • C는 현재보다 이전 버전의 어셈블리 B를 참조하여 작성되었습니다.

누군가를 돕는 희망 - 이걸 알아내는 데 몇 년이 걸렸습니다.

저도 이 오류가 있었습니다. Any CPU exe가 Any CPU 어셈블리를 참조하여 x86 어셈블리를 참조했기 때문입니다.

예외가 MyApp의 클래스에 있는 메서드에 대해 불만을 제기했습니다.MyApp을 파생한 구현(모든 CPU).인터페이스(모든 CPU), 그러나 fuslogvw.exe에서 MyApp에서 숨겨진 '잘못된 형식으로 프로그램을 로드하려고 시도함' 예외를 발견했습니다.두 가지 모두에서 사용되는 공통 유형(x86)입니다.

난 계속 이런 생각이 들어요여기에 나와 있는 많은 답들은 문제가 무엇인지 설명하는 것은 훌륭하지만 해결 방법은 아닙니다.

이에 대한 해결책은 프로젝트 게시 디렉터리에서 bin 파일을 수동으로 삭제하는 것입니다.모든 참조를 정리하고 프로젝트에서 최신 DLL을 사용하도록 강제합니다.

게시 도구 삭제 기능은 IIS를 제거하는 경향이 있으므로 사용하지 않는 것이 좋습니다.

Autofac과 많은 동적 어셈블리 로딩을 사용하는 상황에서 이 오류가 발생했습니다.

자동 팩 확인 작업을 수행하는 동안 런타임이 어셈블리 중 하나를 로드하지 못합니다.오류 메시지는 다음과 같이 불만을 표시했습니다.Method 'MyMethod' in type 'MyType' from assembly 'ImplementationAssembly' does not have an implementation이 증상은 윈도우즈 Server 2012 R2 VM에서 실행될 때 발생했지만 윈도우즈 10 또는 윈도우즈 Server 2016 VM에서는 발생하지 않았습니다.

ImplementationAssemblySystem.Collections.Immutable 1.1.37의 했습니다.IMyInterface<T1,T2>의 터이스로 되었습니다.DefinitionAssembly.DefinitionAssemblySystem.Collections.Immutable1.1.36.

의메드의 IMyInterface<T1,T2>" 에는 " 현되지않은구" " 은유매의개변있다가니수었습지고를형것들▁"▁which" 유형의 변수가 .IImmutableDictionary<TKey, TRow> 정의되어 있는 것은System.Collections.Immutable.

『 』 『 』의 System.Collections.Immutable프로그램 디렉토리에서 발견된 버전은 1.1.37입니다.에는 윈도우즈 서버 2012 R2 VM의 이 되었습니다.System.Collections.Immutable 및 는 1.1.36의 했습니다.System.Collections.Immutable1.1.37.로드 오류는 GAC에 이전 버전의 DLL이 포함되어 있을 때만 발생했습니다.

은 따서어셈로실근원다본대음인은에참다에 대한 가 하지 않았기 입니다.System.Collections.Immutable인터페이스 정의 및 구현은 동일한 모양의 메서드 시그니처를 가지고 있었지만 실제로는 다른 버전의System.Collections.Immutable즉, 런타임이 구현 클래스를 인터페이스 정의와 일치하도록 고려하지 않았습니다.

다음 바인딩 리디렉션을 내 애플리케이션 구성 파일에 추가하여 문제를 해결했습니다.

<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>

이 오류 메시지에 대한 또 다른 난해한 해결책이 있습니다.에서 대상 프레임워크를 업그레이드했습니다.넷 4.0에서 4.6까지, 그리고 제 유닛 테스트 프로젝트는 저에게 "시스템"을 주었습니다.LoadException을 입력합니다.빌드하려고 할 때 구현이 없습니다." 오류가 발생했습니다.또한 "'BuildShadowTask' 작업이 예기치 않게 실패했습니다."라는 동일한 구현되지 않은 메서드에 대한 두 번째 오류 메시지를 제공했습니다.여기에 있는 조언 중 아무 것도 도움이 되지 않는 것 같아 "BuildShadowTask"를 검색하고 MSDN에서 게시물을 찾았는데, 이 게시물을 통해 텍스트 편집기를 사용하여 단위 테스트 프로젝트의 csproj 파일에서 이러한 줄을 삭제했습니다.

<ItemGroup>
  <Shadow Include="Test References\MyProject.accessor" />
</ItemGroup>

그 후, 두 가지 오류가 모두 사라졌고 프로젝트가 구축되었습니다.

저는 "다이아몬드" 모양의 프로젝트 의존성으로 이것을 얻었습니다.

  • 프로젝트 A는 프로젝트 B와 프로젝트 D를 사용합니다.
  • 프로젝트 B는 프로젝트 D를 이용합니다.

나는 A 프로젝트를 다시 컴파일했지만 B 프로젝트가 아니라 B 프로젝트가 D DLL의 이전 버전을 "주입"할 수 있도록 했습니다.

ASP에서 의존하는 프로젝트(및 어셈블리 이름)의 이름을 변경할 때 이 문제가 발생했습니다.NET 프로젝트.웹 프로젝트의 유형이 종속 어셈블리에서 구현된 인터페이스입니다.의 어셈블리가 "Clean Solution"에 있습니다.bin 내 웹 프로젝트가 되었을 때, ▁folder때,을,▁my었더.

var types = AppDomain.CurrentDomain.
   GetAssemblies().
   ToList().
   SelectMany( s => s.GetTypes() /* exception thrown in this call */ )
;

위의 예외는 구현 웹 유형의 인터페이스 메소드가 실제로 구현되지 않았다는 불만으로 던져졌습니다.웹젝트의에서 bin폴더가 문제를 해결했습니다.

이전에 어셈블리 중 하나에 대한 장치 테스트 중에 코드 적용 범위를 활성화했을 때도 이 오류가 발생했습니다.어떤 이유에서인지 Visual Studio는 인터페이스의 새 버전을 구현하기 위해 이 특정 DLL의 이전 버전을 업데이트했음에도 불구하고 "버퍼"했습니다.코드 적용 범위를 비활성화하면 오류가 제거됩니다.

어셈블리를 사용하여 어셈블리를 로드한 경우에도 이 오류가 발생할 수 있습니다.LoadFrom(String)이며 어셈블리를 사용하여 이미 로드된 어셈블리를 참조하고 있습니다.로드(바이트[]).

예를 들어 기본 응용 프로그램의 참조 어셈블리를 리소스로 포함했지만 응용 프로그램은 특정 폴더에서 플러그인을 로드합니다.

LoadFrom을 사용하는 대신 Load를 사용해야 합니다.다음 코드가 작동합니다.

private static Assembly LoadAssemblyFromFile( String filePath )
{
    using( Stream stream = File.OpenRead( filePath ) )
    {
        if( !ReferenceEquals( stream, null ) )
        {
            Byte[] assemblyData = new Byte[stream.Length];
            stream.Read( assemblyData, 0, assemblyData.Length );
            return Assembly.Load( assemblyData );
        }
    }
    return null;
}

참고로, 참조된 어셈블리의 존재하지 않는 버전으로 리디렉션된 구성 파일이 있을 때 이 정보를 얻었습니다.승리를 위한 퓨전 로그!

프레임워크 버전 4.5에 있는 어셈블리 'C'에서 프레임워크 버전 4.5.1에 있는 어셈블리 'A'에서 인터페이스를 구현하고 프레임워크 버전 4.5.1에 있는 어셈블리 'B'의 기본 클래스 역할을 하는 클래스가 있었기 때문에 이 오류가 발생했습니다.어셈블리 'B'를 로드하는 동안 시스템에서 예외를 발생시켰습니다.또한 3개의 어셈블리 모두에 .net 4.5.1을 대상으로 하는 nuget 패키지를 설치했습니다.어떤 이유에서인지 너겟 참조가 어셈블리 'B'에 표시되지 않았지만 성공적으로 빌드되고 있었습니다.

실제 문제는 어셈블리가 인터페이스와 인터페이스 서명이 포함된 다른 버전의 너겟 패키지를 참조하고 있다는 것이었습니다.

관리되는 C++와 관련된 이러한 유형의 문제에 대한 또 다른 설명입니다.

특수 서명이 있는 관리되는 C++을 사용하여 만든 어셈블리에 정의된 인터페이스를 스텁하려고 하면 스텁이 생성될 때 예외가 발생합니다.

Rhino Mocks를 사용하는 합니다.System.Reflection.Emit.

public interface class IFoo {
  void F(long bar);
};

public ref class Foo : public IFoo {
public:
  virtual void F(long bar) { ... }
};

인터페이스 정의는 다음과 같은 서명을 가져옵니다.

void F(System.Int32 modopt(IsLong) bar)

타입은 C++입니다.long에 대한 지도.System.Int32 간단히)intC#)로 표시됩니다.한 것은다불니다합명분소그▁the다▁it입니다.modopt그것은 Rhino Mocks 메일링 리스트에서 Ayende Rahien에 의해 언급된 것처럼 문제를 일으키고 있습니다.

방금 MVC3에서 MVC5로 솔루션을 업그레이드하고 Unit 테스트 프로젝트에서 동일한 예외를 받기 시작했습니다.

오래된 파일을 찾는 모든 참조를 확인했고, 결국 유닛 테스트 프로젝트에서 Mvc에 대한 바인딩 리다이렉트를 수행해야 한다는 것을 알게 되었습니다.

<?xml version="1.0" encoding="utf-8" ?>
<configuration>
  <runtime>
    <assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Helpers" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="1.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.WebPages" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="0.0.0.0-3.0.0.0" newVersion="3.0.0.0" />
      </dependentAssembly>
      <dependentAssembly>
        <assemblyIdentity name="System.Web.Mvc" publicKeyToken="31bf3856ad364e35" />
        <bindingRedirect oldVersion="0.0.0.0-5.1.0.0" newVersion="5.1.0.0" />
      </dependentAssembly>
    </assemblyBinding>
  </runtime>
</configuration>

저의 경우 WinForms Toolbox를 재설정하는 데 도움이 되었습니다.

오픈할 때 예외가 발생했습니다.Form그러나 코드를 컴파일하고 실행하는 것은 가능했고 코드는 예상대로 작동했습니다. 로서예발니다에서 했습니다.UserControl참조된 라이브러리 중 하나에서 인터페이스를 구현하는 중입니다.이 라이브러리를 업데이트한 후 오류가 발생했습니다.

것이.UserControlWinForms 도구 상자에 나열되어 있습니다.Visual Studio가 라이브러리의 오래된 버전에 대한 참조를 유지했거나 어딘가에 오래된 버전을 캐싱하고 있었을 수 있습니다.

이 상황에서 회복한 방법은 다음과 같습니다.

  1. 상자를 오른쪽 단추로 하고 WinForms 도구마오스른단클다릭합다니음을클고를 클릭합니다.Reset Toolbox도구 상자에서 사용자 정의 항목을 제거합니다.
    내 경우 도구 상자 항목이 기본 상태로 복원되었지만 도구 상자에 포인터 화살표가 없습니다.
  2. 비주얼 스튜디오입니다.
    이 경우 Visual Studio가 위반 예외로 종료되어 중단되었습니다.
  3. Visual Studio 다시합니다작시를▁visual.
    이제 모든 것이 순조롭게 진행되고 있습니다.

, 나는 에 저경우, 저이에전을 한 적이 .mylib에 있는 를 - 보서외부형폴있더에는 - 게부르자라고 v1.0.

|-- myrepo
|    |-- consoleApp
|    |-- submodules
|         |-- mylib (submoduled v2.0)
|-- mylib (stale v1.0)

나중에 나는 그것을 제대로 했고 깃 서브모듈을 통해 그것을 사용했습니다 - 전화를 걸어봅시다.v2.0하나의 프로젝트consoleApp하지만 제대로 업데이트되지 않았습니다.그것은 여전히 오래된 것을 참조하고 있었습니다.v1.0내 git 프로젝트 외부의 프로젝트.

혼란스럽게도, 비록.*.csproj분명히 틀렸고 지적했습니다.v1.0는 Visual Studio IDE의 .v2.0프로젝트!인터페이스를 검사하기 위해 F12를 사용하고 수업은 다음으로 갔습니다.v2.0버전도.

는 러에의해폴더는어리셈블배된치에컴파일▁the▁the▁placed는▁by▁assembly리블.v1.0버전, 따라서 두통.

IDE가 나에게 거짓말을 하고 있다는 사실은 그 오류를 깨닫는 것을 더욱 어렵게 만들었습니다.

솔루션:프로젝트 참조를 삭제했습니다.ConsoleApp그리고 그것들을 추가했습니다.

일반 팁: 모든 어셈블리를 처음부터 다시 컴파일하고(가능한 경우 nugget 패키지는 물론 할 수 없음) 날짜/시간 스탬프를 확인합니다.bin\debug폴더를 누릅니다.오래된 어셈블리가 문제입니다.

저는 거의 같은 문제에 직면했습니다.나는 이 오류의 원인이 무엇인지 머리를 긁적거리고 있었습니다.확인해보니 모든 방법이 실행되었습니다.

구글링에서 저는 다른 것들 중에서 이 링크를 얻었습니다.@Paul McLink 의견을 바탕으로, 이 두 단계는 문제를 해결했습니다.

  1. Visual Studio 다시 시작
  2. 새로 고침, 빌드(재구축)

오류가 사라졌습니다.

VS 플러그인 다시 시작

폴 감사합니다 :)

이것이 이 오류를 발견한 누군가에게 도움이 되기를 바랍니다 :)

저는 또한 유닛 테스트를 실행하는 동안 이 문제에 부딪혔습니다.응용 프로그램이 오류 없이 정상적으로 실행되었습니다.저의 경우 문제의 원인은 테스트 프로젝트의 빌드를 껐기 때문입니다.테스트 프로젝트를 다시 구축함으로써 문제가 해결되었습니다.

Visual Studio Pro 2008에서 두 프로젝트가 동일한 이름의 어셈블리를 만들었을 때 이를 보았습니다. 하나는 클래스 lib SDF.dll이고 다른 하나는 어셈블리 이름이 sdf.exe인 lib를 참조했습니다.참조 어셈블리의 이름을 변경했을 때 예외가 사라졌습니다.

이는 제 경우 구현 프로젝트가 구식이라는 것을 의미합니다.인터페이스를 포함하는 DLL이 재구성되었지만 구현 DLL이 오래되었습니다.

이 오류에 대한 저의 견해는 이렇습니다.

이 되었습니다.extern방법, 하지만 내 페이스트는 결함이 있었습니다.DllImportAttribute코멘트 아웃라인에 올려졌습니다.

/// <returns>(removed for brevity lol)</returns>[DllImport("user32.dll")] 
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool IsWindowVisible(IntPtr hWnd);

속성이 실제로 소스에 포함되었는지 확인하여 문제를 해결했습니다.

x86 빌드 유형이 선택되어 있어 빈이 빈이 아닌 bin\x86 아래에서 살게 되어 WCF 서비스에서 이를 얻었습니다.임의의 CPU를 선택하면 다시 컴파일된 DLL이 올바른 위치로 이동합니다(처음에 어떻게 이런 일이 발생했는지 자세히 설명하지 않겠습니다).

사용자 지정 AssemblyLoadContext(AppDomain 생성 없음)와 공유 유형(반영 없이 플러그인 메서드를 호출하는 데 사용해야 하는 인터페이스)을 사용하여 닷넷 5에서 플러그인 어셈블리 로드를 구현하려고 할 때 이 문제가 발생했습니다.이 실타래로 얻은 것은 아무것도 도움이 되지 않았습니다.이 문제를 해결하기 위해 제가 한 일은 다음과 같습니다.

  1. 플러그인 로드 디버깅을 문제 없이 허용하려면 - 호스트 앱 bin 폴더에 대한 프로젝트 출력 경로를 설정합니다.플러그인 프로젝트 빌드 후 얻은 것과 동일한 어셈블리를 디버그합니다.이것은 아마도 일시적인 변경일 것입니다(디버깅용일 뿐).
  2. TypeLoadException을 수정하려면 모든 '계약 어셈블리' 참조 어셈블리를 공유 어셈블리로 로드해야 합니다(런타임 어셈블리 제외).로더 컨텍스트 구현 확인(생성자에서 공유 어셈블리 로드):

    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>()...

저도 같은 문제가 있었습니다.메인 프로그램에서 로드하는 어셈블리에 "로컬 복사"가 true로 설정된 참조가 있음을 알게 되었습니다.이러한 로컬 참조 복사본은 동일한 폴더에서 다른 참조를 찾고 있습니다. 다른 참조의 "로컬 복사"가 false로 설정되었기 때문에 존재하지 않았습니다.실수로 복사된 참조를 삭제한 후 메인 프로그램이 올바른 참조 위치를 찾도록 설정되었기 때문에 오류가 사라졌습니다.참고 문헌의 로컬 복사본이 메인 프로그램에 있는 원본 대신 사용되었기 때문에 호출 순서를 망쳤습니다.

이 오류는 필요한 어셈블리를 로드할 링크가 없기 때문에 발생한다는 메시지입니다.

제 경우에는, 저는 사용하려고 했습니다.TypeBuilder유형을 만듭니다. TypeBuilder.CreateType이 예외를 던졌습니다.저는 결국 제가 추가할 필요가 있다는 것을 깨달았습니다.MethodAttributes.Virtual을 호출할 때 TypeBuilder.DefineMethod인터페이스를 구현하는 데 도움이 되는 방법입니다.플래그가 구현하기 입니다.MethodAttributes.NewSlot).

부록: 가짜 어셈블리를 생성하는 데 사용된 너트 패키지를 업데이트하는 경우에도 이러한 문제가 발생할 수 있습니다.Nugget 패키지의 V1.0을 설치하고 가짜 어셈블리 "fakeLibrary.1.0.0.0"을 생성한다고 가정합니다.가짜." 다음으로, 인터페이스에 새로운 메서드를 추가한 v1.1과 같은 nuget 패키지의 최신 버전으로 업데이트합니다.Fake 라이브러리는 여전히 라이브러리의 v1.0을 찾고 있습니다.가짜 어셈블리를 제거하고 재생성하기만 하면 됩니다.그것이 문제였다면, 아마 이것이 그것을 해결할 것입니다.

언급URL : https://stackoverflow.com/questions/948785/typeloadexception-says-no-implementation-but-it-is-implemented

반응형