Type.GetType (“ namespace.abClassName”) ส่งคืนค่าว่าง


216

รหัสนี้:

Type.GetType("namespace.a.b.ClassName")

nullผลตอบแทน

และฉันมีในการใช้:

using namespace.a.b;

ปรับปรุง:

มีชนิดอยู่ในไลบรารีคลาสอื่นและฉันต้องการได้โดยใช้ชื่อสตริง


ดูstackoverflow.com/questions/441680/นี้สำหรับข้อมูลเกี่ยวกับวิธีรับชื่อที่ผ่านการรับรอง
Polyfun

คำตอบ:


244

Type.GetType("namespace.qualified.TypeName") ใช้ได้เฉพาะเมื่อพบชนิดใน mscorlib.dll หรือแอสเซมบลีที่กำลังดำเนินการอยู่ในปัจจุบัน

หากสิ่งเหล่านั้นไม่เป็นจริงคุณจะต้องมีชื่อที่มีคุณสมบัติการประกอบ :

Type.GetType("namespace.qualified.TypeName, Assembly.Name")

3
ประเภทที่มีอยู่ก็อยู่ในห้องสมุดชั้นที่แตกต่างกันและฉันต้องการที่จะได้รับมันโดยใช้ชื่อสตริง
Omu

25
แทนการใช้ชื่อการชุมนุมที่ผ่านการคัดเลือกคุณสามารถโหลดการชุมนุมโดยใช้ชื่อ - Assembly a = Assembly.Load("SomeLibrary");- แล้วโหลดชนิดโดยใช้ชื่อจากการชุมนุม Type t = a.GetType("namespace.a.b.ClassName");-
Kenny Evitt

6
บางทีคุณอาจชอบtypeof(SomeTypeInThatAssembly).Assembly.GetTypes().Where((t) => t.FullName == youFullName);อาจประหยัดความยุ่งยากในที่สุด
Felype

คำตอบของ Felype เป็นเพียงสิ่งเดียวที่ฉันสามารถทำงานได้
Rudy Scoggins

เพิ่ม .FirstOrDefault () ไปยัง @Felype ความคิดเห็น
Leandro

173

คุณยังสามารถรับชนิดโดยไม่มีชื่อประกอบที่มีคุณสมบัติ แต่ด้วยชื่อ dll เช่น:

Type myClassType = Type.GetType("TypeName,DllName");

ฉันมีสถานการณ์เดียวกันและใช้งานได้สำหรับฉัน ฉันต้องการวัตถุประเภท "DataModel.QueueObject" และมีการอ้างอิงถึง "DataModel" ดังนั้นฉันจึงได้ชนิดดังนี้:

Type type = Type.GetType("DataModel.QueueObject,DataModel");

สตริงที่สองหลังเครื่องหมายจุลภาคคือชื่ออ้างอิง (ชื่อ dll)


2
นี่เป็น 'เคล็ดลับ' หรือวิธีการจริงหรือไม่? ฉันไม่พบสิ่งนี้ในเอกสาร -_- โดยวิธีการมันจบ 1 สัปดาห์ของฉันประสบ! ขอบคุณ
DnR

1
นี่เป็นวิธีที่สะอาดกว่านี้มากฉันชอบที่จะดูว่ามีข้อผิดพลาดหรือไม่เพราะเหตุนี้
คอสแซคแมน

4
แบบฟอร์มที่ใช้ในคำตอบนี้เป็นชื่อชนิดที่ผ่านการรับรองตามไวยากรณ์ MSDN (ดังนั้นจึงไม่ใช่เคล็ดลับ ) รูปแบบเป็นNamespaceTypeName, AssemblyNameSpecที่ที่AssemblyNameSpecเป็นตัวระบุของการชุมนุมโดยไม่มีคุณสมบัติใด ๆ แม้ว่าคำตอบนี้จะเป็นแบบเดียวกับที่ยอมรับฉันคิดว่าบางคนชอบสิ่งนี้เพราะมันมี "เสียงรบกวน" บางอย่างที่คุณสมบัติการชุมนุมแนะนำ (เช่นVersion, Culture PublicKeyToken) โชคดีที่มีคุณสมบัติเป็นตัวเลือก
Martin Liversage

สำหรับประเภทที่ซ้อนกันคุณอาจต้องทำอะไรบางอย่างAtlasKernelBusinessModel.AtlasConstants+ClaimCoverage+Status,AtlasKernelBusinessModel
toddmo

ขอบคุณมันใช้งานได้กับโฟลเดอร์ App_Code ตัวอย่าง: Type.GetType ("TypeName, App_Code");
Burak Koray Balcı

79

ลองใช้วิธีนี้

 public static Type GetType(string typeName)
        {
            var type = Type.GetType(typeName);
            if (type != null) return type;
            foreach (var a in AppDomain.CurrentDomain.GetAssemblies())
            {
                type = a.GetType(typeName);
                if (type != null)
                    return type;
            }
            return null ;
        }

นี่คือสิ่งที่ใช้งานได้จริงสำหรับฉัน ฉันต้องปรับแต่งโดยการเพิ่มการตัดย่อยย่อยก่อน foreach loop แต่เนื่องจากฉันผ่านชื่อที่มีคุณสมบัติการประกอบและ Assembly.GetType () จะทำงานเฉพาะในกรณีที่คุณไม่รวมข้อมูลการประกอบ
โคลิน

สิ่งนี้ดูดี แต่สิ่งที่เกี่ยวกับ generics โดยใช้ประเภทการชุมนุมอื่น ๆ ?
Demetris Leptos

ใช้งานไม่ได้กับ UWP เพราะAppDomainไม่รองรับ ไม่แน่ใจในทางเลือกใด ๆ
James M

25
Dictionary<string, Type> typeCache;
...
public static bool TryFindType(string typeName, out Type t) {
    lock (typeCache) {
        if (!typeCache.TryGetValue(typeName, out t)) {
            foreach (Assembly a in AppDomain.CurrentDomain.GetAssemblies()) {
                t = a.GetType(typeName);
                if (t != null)
                    break;
            }
            typeCache[typeName] = t; // perhaps null
        }
    }
    return t != null;
}

1
สิ่งนี้ดูดี แต่สิ่งที่เกี่ยวกับ generics โดยใช้ประเภทการชุมนุมอื่น ๆ ?
Demetris Leptos

1
@DemetrisLeptos (ฉันรู้ว่าความคิดเห็นนั้นเก่า - แต่คนอื่น ๆ อาจสนใจ): ใช้ int index = typeName.IndexOf ('`'); if (index> 0) {typeName = _typeName.Substring (0, index + 2); } โปรดทราบว่าTประเภททั่วไปถูกถอดออก
Bernhard Hiller

25

หากแอสเซมบลีเป็นส่วนหนึ่งของบิลด์ของแอปพลิเคชัน ASP.NET คุณสามารถใช้คลาส BuildManager ได้:

using System.Web.Compilation
...
BuildManager.GetType(typeName, false);

1
นี่คือคำตอบที่ยอดเยี่ยมและควรจะสูงขึ้นในหน้า ทำงานเหมือนมีเสน่ห์และดูเรียบง่ายเมื่อเทียบกับวิธีการรับชื่อประเภทที่ผ่านการรับรองของชุดประกอบ
เกรแฮม

นี่เป็นเรื่องง่ายและน่าทึ่งคุณสามารถช่วยฉันเพิ่มประสิทธิภาพการทำงานของวัตถุสะท้อนได้หรือไม่
Alok

15

หากคลาสของคุณไม่ได้อยู่ใน assambly ปัจจุบันคุณต้องให้ชื่อที่ผ่านการรับรองและรหัสนี้จะแสดงวิธีรับชื่อที่ผ่านการรับรองของคลาส

string qualifiedName = typeof(YourClass).AssemblyQualifiedName;

จากนั้นคุณจะได้รับประเภทที่ผ่านการรับรองชื่อ

Type elementType = Type.GetType(qualifiedName);

8

หากเป็นประเภทที่ซ้อนกันคุณอาจลืมแปลง เพื่อ +

โดยไม่คำนึงถึง typeof( T).FullNameจะบอกอะไรคุณควรพูด

แก้ไข: BTW การใช้งาน (ตามที่ฉันแน่ใจว่าคุณรู้) เป็นเพียงคำสั่งให้รวบรวมในเวลารวบรวมและดังนั้นจึงไม่สามารถมีผลกระทบใด ๆ กับความสำเร็จของการเรียก API (หากคุณมีโครงการหรือการอ้างอิงแอสเซมบลีที่อาจมีอิทธิพล - ดังนั้นข้อมูลไม่ไร้ประโยชน์มันใช้ตัวกรองบางอย่าง ... )


พุทโธ่! คุณรู้หรือไม่ว่าคำสั่ง "+" นี้มีการอธิบายเกี่ยวกับไวยากรณ์หรือไม่
ป้องกันหนึ่ง

1
ผู้คุ้มครองฉันเรียนรู้จากamazon.com/Essential-NET-Common-Language-Runtime/dp/0201734117 IIRC แต่มันเก่าไปหน่อย ฉันสามารถแนะนำamazon.com/CLR-via-4th-Developer-Reference/dp/0735667454/เป็นหนังสือที่มีประโยชน์มากสำหรับ devs .NET ทั้งหมดรวมถึงสิ่งนี้หรือไม่ บรรทัดล่างคือสำหรับประเภท CLR มีเนมสเปซและชื่อเท่านั้น - ประเภทที่ซ้อนกันไม่สามารถกำหนดแอดเดรสได้โดยตรง ดังนั้นภาษาถ้ามันมีแนวคิดแบบซ้อนกันได้ทำในสิ่งที่ต้องการ (แม้ว่าโดยทั่วไปแลงส่วนใหญ่จะใช้+ตัวคั่น)
Ruben Bartelink

6

ฉันกำลังเปิดการควบคุมผู้ใช้ขึ้นอยู่กับสิ่งที่ผู้ใช้ควบคุมผู้ใช้มีการเข้าถึงที่ระบุในฐานข้อมูล ดังนั้นฉันใช้วิธีนี้เพื่อรับ TypeName ...

Dim strType As String = GetType(Namespace.ClassName).AssemblyQualifiedName.ToString
Dim obj As UserControl = Activator.CreateInstance(Type.GetType(strType))

ดังนั้นตอนนี้เราสามารถใช้ค่าที่ส่งคืนใน strType เพื่อสร้างอินสแตนซ์ของวัตถุนั้น


เปิดหัวข้อใหม่ที่ยิ่งใหญ่ ... ขอแสดงความยินดี อย่างไรก็ตามฉันต้อง downvote คำตอบของคุณเพราะ TO รู้ชื่อ Typename จริง ๆ และต้องการรับประเภทจากมัน Btw: คุณใช้วิธีการใดในการอ้างอิงโดย <c> GetType (Namespace.ClassName) </c> ถ้า Type.GetType มันจะทำงานเฉพาะกับประเภทที่อยู่ในแอสเซมบลีที่กำลังเรียกใช้งานหรือ mscorlib ของคุณ แต่จะไม่มีใคร ของเงื่อนไขเหล่านี้ใช้
HimBromBeere

2
@HimBromBeere ขอบคุณสำหรับการลงคะแนน เป็นคนอย่างคุณที่ลดระดับฉันให้โพสต์สิ่งที่ฉันค้นพบ ฉันยังคงเรียนรู้พัฒนาการและฉันแค่พยายามช่วยเหลือผู้อื่น และตอนนี้คุณคาดหวังให้ฉันตอบคำถามของคุณ? โดยวิธีการที่ฉันได้ตอบคำถามอย่างถูกต้อง คลาสที่ฉันสร้างอินสแตนซ์ของการอยู่ในโครงการอื่นและต้องใช้ชื่อ AssemblyQualified เนื่องจากสิ่งนั้น ดังนั้นโปรดอ่านความคิดเห็นที่เหลือก่อนที่จะทำการ downvoting "ประเภทนี้มีอยู่ในไลบรารีคลาสอื่นและฉันจำเป็นต้องใช้ชื่อสตริง - Omu"
Stephan

6

เมื่อฉันมีเพียงชื่อชั้นฉันใช้สิ่งนี้:

Type obj = AppDomain.CurrentDomain.GetAssemblies().SelectMany(t => t.GetTypes()).Where(t => String.Equals(t.Name, _viewModelName, StringComparison.Ordinal)).First();

5

ในฐานะที่เป็นType.GetType (String)ต้องType.AssemblyQualifiedNameคุณควรใช้Assembly.CreateQualifiedName (String, String)

string typeName = "MyNamespace.MyClass"; // Type.FullName
string assemblyName = "MyAssemblyName"; // MyAssembly.FullName or MyAssembly.GetName().Name
string assemblyQualifiedName = Assembly.CreateQualifiedName(assemblyName , typeName);
Type myClassType = Type.GetType(assemblyQualifiedName);

ไม่จำเป็นต้องใช้เวอร์ชัน, วัฒนธรรมและ PublicKeyToken เพื่อassemblyNameให้คุณสามารถใช้ MyAssembly.GetName ()

เกี่ยวกับType.GetType (สตริง) :

ถ้าชนิดอยู่ในแอสเซมบลีที่กำลังดำเนินการอยู่ในปัจจุบันหรือใน Mscorlib.dll มันก็เพียงพอที่จะระบุชื่อชนิดที่มีคุณสมบัติตาม namespace


4

หากมีการอ้างอิงแอสเซมบลีและคลาสที่มองเห็นได้:

typeof(namespace.a.b.ClassName)

GetType ส่งคืนค่า null เนื่องจากไม่พบชนิดด้วย typeof คอมไพเลอร์อาจช่วยคุณค้นหาข้อผิดพลาด


ประเภทที่มีอยู่ก็อยู่ในห้องสมุดชั้นที่แตกต่างกันและฉันต้องการที่จะได้รับมันโดยใช้ชื่อสตริง
Omu

4

ลองใช้ชื่อเต็มประเภทที่มีข้อมูลประกอบตัวอย่างเช่น:

string typeName = @"MyCompany.MyApp.MyDomain.MyClass, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null";
Type myClassType = Type.GetType(typeName);

ฉันมีสถานการณ์เดียวกันเมื่อฉันใช้ namesspace.classname เพื่อรับชนิดของคลาสในชุดประกอบอื่นและจะไม่ทำงาน ทำงานได้เฉพาะเมื่อฉันรวมข้อมูลการประกอบในสตริงประเภทของฉันตามที่แสดงด้านบน


3

ตรวจสอบให้แน่ใจว่าเครื่องหมายจุลภาคอยู่หลังชื่อที่ผ่านการรับรองโดยสมบูรณ์

typeof(namespace.a.b.ClassName, AssemblyName)

เช่นนี้จะไม่ทำงาน

typeof(namespace.a.b.ClassName ,AssemblyName)

ฉันนิ่งงันอยู่สองสามวันกับสิ่งนี้


2

สำหรับฉัน "+" คือกุญแจ! นี่คือชั้นเรียนของฉัน (เป็นชั้นซ้อน):

namespace PortalServices
{
public class PortalManagement : WebService
{
    public class Merchant
    {}
}
}

และบรรทัดของรหัสนี้ทำงาน:

Type type = Type.GetType("PortalServices.PortalManagement+Merchant");

1

นี้การแก้ปัญหาดังกล่าวข้างต้นน่าจะเป็นสิ่งที่ดีที่สุดให้ฉัน แต่มันไม่ได้ทำงานสำหรับฉันดังนั้นฉันไม่ได้ดังต่อไปนี้:

AssemblyName assemblyName = AssemblyName.GetAssemblyName(HttpContext.Current.Server.MapPath("~\\Bin\\AnotherAssembly.dll"));
string typeAssemblyQualifiedName = string.Join(", ", "MyNamespace.MyType", assemblyName.FullName);

Type myType = Type.GetType(typeAssemblyQualifiedName);

เงื่อนไขเบื้องต้นคือคุณรู้เส้นทางของการชุมนุม ในกรณีของฉันฉันรู้เพราะนี่คือการชุมนุมที่สร้างขึ้นจากโครงการภายในอื่นและรวมอยู่ในโฟลเดอร์ถังขยะของโครงการของเรา

ในกรณีที่ฉันใช้ Visual Studio 2013 เป้าหมายของฉันคือ. NET 4.0 นี้เป็นโครงการที่ ASP.NET HttpContextดังนั้นฉันได้รับผ่านเส้นทางที่แน่นอน อย่างไรก็ตามเส้นทางแบบสัมบูรณ์ไม่ใช่ข้อกำหนดตามที่ดูเหมือนจากMSDN บน AssemblyQualifiedNames


0

ฉันโกง เนื่องจากประเภทที่ฉันต้องการสร้าง (ตามชื่อ) ล้วนอยู่ในใน dll ที่ฉันควบคุมฉันเพิ่งใส่วิธีแบบคงที่ใน dll ในแอสเซมบลีที่ใช้ชื่อแบบง่ายและเรียกใช้ type.GetType จากบริบทนั้นและส่งกลับผลลัพธ์ .

วัตถุประสงค์ดั้งเดิมคือเพื่อให้สามารถระบุประเภทตามชื่อในข้อมูลการกำหนดค่า ฉันได้เปลี่ยนรหัสเพื่อให้ผู้ใช้ระบุรูปแบบที่จะดำเนินการ คลาสตัวจัดการรูปแบบใช้อินเตอร์เฟสที่กำหนดว่าชนิดสามารถวิเคราะห์รูปแบบที่ระบุได้หรือไม่ ฉันใช้การสะท้อนเพื่อค้นหาชนิดที่ใช้อินเทอร์เฟซและค้นหาชนิดที่จัดการรูปแบบ ดังนั้นตอนนี้การกำหนดค่าจะระบุชื่อรูปแบบไม่ใช่ประเภทเฉพาะ รหัสสะท้อนสามารถดูที่กำลังติดตั้งและโหลดได้ดังนั้นฉันจึงมีสถาปัตยกรรมปลั๊กอินของคนจนเรียงลำดับ


สวัสดีฉันลงคะแนนโดยไม่ได้ตั้งใจโปรดแก้ไขคำตอบของคุณเพื่อให้ฉันสามารถยกเลิกได้
coloboxp
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.