2017-11-15 8 views
0

동적으로 생성 된 유형의 객체를 생성 했으므로 런타임에로드 된 함수를 호출하려고합니다. :와동적 호출에서 ""myObject '유형의 객체를'myObject '유형으로 변환 할 수 없습니다. "

인보 호출 예외 {System.ArgumentException :. 유형 'UserClasses.re_Constituent'의 개체 'UserClasses.re_Constituent을'형식으로 변환 할 수없는}

(예 그 2 개 클래스가 동일)

클래스, 및 호출 된 함수의 코드에 대한 코드는 이전에 생성에 따라 컴파일 된 https://stackoverflow.com/a/3024112/432976

사람이 오류의 원인을 알고 있나요?


코드의 호출 라인에 일시 magicValue 호출 (다음 코드 예외)

namespace myTest 
{ 
    internal class Program 
    { 
    Main(){ 
     //pseudoCode 
     BuildTypes(); 
     {Type myType,MethodInfo myMethod} = factory.getType("re_Constituent"); 

     //actual code that exceptions 
     Node result = (Node) JSON.Deserialize(textstream,myType); 
     object magicValue = myMethodInfo.Invoke(null,new object[]{result}); 
    } 
} 
namespace UserClasses 
{ 
    public abstract class Node 
    {} 
} 

inspecing 계시한다 :

myMethodInfo이다 : { System.Collections.Generic. List`1 [UserClasses.Node] ConvertToCore (UserClasses.re_Constituent)}

methodInfo에 의해 예상되는 매개 변수의 유형은 다음과 같습니다."UserClasses.re_Constituent, dynamicGen_reApi_3, 버전 = 0.0.0.0, 중립 문화 =, PublicKeyToken = null이가"

json으로 역 직렬화 (즈 질)에 전달 된 유형은 다음과 같이 표시됩니다 : "UserClasses.re_Constituent, dynamicGen_reApi_3, 버전 = 0.0.0.0, 문화 = 중립, PublicKeyToken = null이 "

result.GetType() AssemblyQualifiedName :. "UserClasses.re_Constituent, dynamicGen_reApi_3, 버전 = 0.0.0.0, 문화 = 중립, PublicKeyToken = null이 "

re_Constituent는 별도로 동적으로로드 된 dll로 정의됩니다.

namespace UserClasses 
{ 
    public class re_Constituent : Node 
    { 
    public string id; 
    ... other fields 
    } 
} 

함수에 대한 코드는 다른 런타임으로로드 된 DLL에서 발견된다 :

namespace UserClasses 
{ 
    public static class MyExtensions 
    { 
    public static List<Node> ConvertToCore(this re_Constituent node) 
    { 
     return new List<Node>() 
     { 
     new Node(); // actual code is more complex here 
     }; 
    } 
    } 
} 

내가 모든 어셈블리의 모든 클래스를 반복하여 내 동적 생성/로딩 뭔가 재미를 발견로드하는 빌드 된 어셈블리의 복사본이 2 개 메모리에 있음을 보여줍니다.

foreach (Assembly assembly in AppDomain.CurrentDomain.GetAssemblies()) 
{ 
    if(!assembly.GetName().Name.StartsWith("System")) 
    foreach (Type type in assembly.GetTypes()) 
    { 
     if(type.FullName.Name.StartsWith("System")) 
      Console.WriteLine(type+":"+assembly.GetName().Name); 
    } 
} 

답변

1

컴파일 할 때 코드가로드 될 때까지 클래스는 일반 형식 확인 시스템에서 사용할 수 없게됩니다. 이 문제 https://stackoverflow.com/a/3024112/432976 를 해결하려면 최종 컴파일에 대한 코드가 있습니다

AppDomain.CurrentDomain.Load(results.CompiledAssembly.GetName()); 
    return results.CompiledAssembly; 

문제를 .Load 호출에서 반환 조립 읽기 컴파일 결과에서 이미 메모리 조립과 같은 객체가되지 않는 것입니다 .

내 문제는 형식에 대해 반환 된 어셈블리를 검사하고 향후 사용을 위해 캐싱하는 것이므로 re_constituent의 버전이 실제로 유형 시스템에서 알고있는 re_constituent의 버전과 다르다는 것을 의미합니다.

이 문제를 해결하려면 사용자 코드에 노출에만 1 어셈블리 버전이로드 된 버전을 반환하여이 있는지 확인하십시오 :

return AppDomain.CurrentDomain.Load(results.CompiledAssembly.GetName());