2010-03-02 12 views
19

W wielu miejscach napotykam częściowo kwalifikowane nazwy typu o postaci FullTypeName, AssemblyName, tj. Takie jak Type.AssemblyQualifiedName tylko bez kwalifikatorów wersji, kultury i publicKeyToken.Jak działa Type.GetType, gdy podano nazwę częściowo kwalifikowanego typu?

Moje pytanie brzmi: jak można go przekonwertować na odpowiedni Type przy minimalnym wysiłku? Myślałem, że wykonuje to zadanie, ale niestety nie. Poniższy kod, na przykład, zwraca null:

Type.GetType("System.Net.Sockets.SocketException, System"); 

Oczywiście, gdybym podać pełną nazwę to działa:

Type.GetType("System.Net.Sockets.SocketException, System, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089"); 

dzięki.

+0

Czy masz typ w czasie kompilacji? Jeśli tak, dlaczego nie użyć typeof () .FullName, et. glin? Jeśli masz typ w czasie wykonywania, możesz użyć .GetType(). FullName et. glin. Czy może brakuje mi konkretnej prośby? Rozumiem, że chcesz tylko podać nazwę częściową, ale to naprawdę bardziej dla programu ładującego niż dla systemu typu. FQN służą do rozróżniania problemów referencyjnych w rzadkich przypadkach, w których występują konflikty nazw, co jest prawdą częściej w złożeniach użytkowników niż w zespołach BCL. – GrayWizardx

+1

Jestem w pełni świadomy typeof() lub Type.FullName. Typ obiektu jest odczytywany z pliku konfiguracyjnego, dlatego używam Type.GetType. I właśnie dlatego tak bardzo zależy mi na zrozumieniu, jak działają częściowo kwalifikowane nazwy typów. – mark

Odpowiedz

8

Jeśli biblioteka DLL, w której się znajduje, nie jest już załadowana do domeny aplikacji (np. Użyłaś go), potrzebujesz pełnej ścieżki takiej jak ta, jeśli jest już załadowana, może znaleźć ją w krótszej wersji.

Aby odpowiedzieć na twoje pytanie: druga wersja zawsze działa, trzymaj się go i masz jeden sposób, aby się martwić.

+1

Nie sądzę, aby miało to znaczenie, czy zestaw jest już załadowany - krótka wersja nie będzie działać. Nazwa kwalifikowana przestrzeni nazw będzie działać, jeśli typ jest albo w aktualnie wykonywanym złożeniu, albo w mscorlib. Pełniejsze wyjaśnienie poniżej. – lesscode

2

Kodeks pracy z krótkiej formy jest:

Assembly a = Assembly.LoadWithPartialName(assemblyName); 
    Type t = a.GetType(typeName); 

ale LoadWithPartialName jest przestarzała, więc myślę, że należy trzymać się z długiej formie.

29

Jeśli zespół został załadowany w bieżącej domenie następnie kod poniżej zazwyczaj działa:

public static Type GetTypeEx(string fullTypeName) 
{ 
    return Type.GetType(fullTypeName) ?? 
      AppDomain.CurrentDomain.GetAssemblies() 
        .Select(a => a.GetType(fullTypeName)) 
        .FirstOrDefault(t => t != null); 
} 

Można go używać tak:

Type t = GetTypeEx("System.Net.Sockets.SocketException"); 
+1

Dziękuję bardzo za tę odpowiedź! Dokładnie tego szukałem - znacznie lepiej niż "zaakceptowana" odpowiedź. –

+2

Pamiętaj tylko, że może to być bardzo powolne, więc nie zapomnij o cache'u. – nawfal

2

Po prostu przeszedł podobny problem z jakiś staroświecki kod, nie sądzę, że pierwsze zdanie w zaakceptowanej odpowiedzi jest poprawne. Nie ma znaczenia, czy zestaw jest już załadowany.

Zgodnie z dokumentacją, Type.GetType(string) wymaga AssemblyQualifiedName, chyba że dany typ znajduje się w aktualnie wykonywanym zespole lub w mscorlib, w którym to przypadku nazwa typu kwalifikowanego dla przestrzeni nazw jest wszystkim, co jest wymagane.

Należy pamiętać, że AssemblyQualifiedName zawiera pełną DisplayName zespołu typu (z wersją, kulturą i tokerem klucza publicznego).

Krótka wersja nie będzie działać, dopóki nie przechwycisz nieudanego typu obciążenia niestandardowym AssemblyResolver (co w rzeczywistości było z moim problemem, zamaskowanie innego problemu).

0

Prawda, Type.GetType (ciąg) wymaga pozycji AssemblyQualifiedName.To może być w wielu formach:

MyNS.MyType, MyAssembly, Version=x.x.x.x, Culture=xxx, PublicKeyToken=XXXXXXXXXX 

Poniżej są również ważne AssemblyQualifiedNames:

MyNS.MyType, MyAssembly, Version=x.x, Culture=xxx, PublicKeyToken=XXXXXXXXXX 
MyNS.MyType, MyAssembly, Culture=xxx, PublicKeyToken=XXXXXXXXXX 
MyNS.MyType, MyAssembly, PublicKeyToken=XXXXXXXXXX 
MyNS.MyType, MyAssembly 

za podpisanym montażu, minimalna wymagana dla FullyQualifiedAssemblyName jest:

MyNS.MyType, MyAssembly, PublicKeyToken=XXXXXXXXXX 

dla Niepodpisany zbiór, minimalna wymagana dla w pełni kwalifikowanej nazwy zgłoszenia to:

MyNS.MyType, MyAssembly 

Nie ma potrzeby wykonywania "machania ręką" w podanych fragmentach kodu. Upewnij się, że nazwy typów są poprawnie skonfigurowane i możesz uzyskać dostęp do typów (i dynamicznie ładować złożenia) z dużą elastycznością. Robię to regularnie.

W przykładzie OP na podstawie:

Type.GetType("System.Net.Sockets.SocketException, System") 

Przyczyną niepowodzenia była nieobecność TokenKluczaPublicznego. Zespoły .Net FW są podpisane i dlatego wymagają klucza PublicKey, aby rozpoznać nazwę zespołu. Następujące działa:

Type.GetType("System.Net.Sockets.SocketException, System, PublicKeyToken=b77a5c561934e089") 
Powiązane problemy