วิธีการตรวจสอบว่าวัตถุมีวิธีการ / คุณสมบัติบางอย่าง?


155

ใช้รูปแบบไดนามิกอาจ? คุณสามารถเรียกวิธีการ / คุณสมบัติใด ๆ โดยใช้คำสำคัญแบบไดนามิกใช่ไหม? วิธีการตรวจสอบว่ามีวิธีการก่อนที่จะเรียก myDynamicObject.DoStuff () ตัวอย่างเช่น?


myDynamicObjectประเภทใด มันเป็นคลาสที่ได้มาจากDynamicObjectไหน?
เฉินเฉิน

สิ่งที่ประกาศด้วยคำสำคัญแบบไดนามิก
Louis Rhys

คำตอบ:


224

คุณสามารถเขียนบางอย่างเช่นนั้น:

public static bool HasMethod(this object objectToCheck, string methodName)
{
    var type = objectToCheck.GetType();
    return type.GetMethod(methodName) != null;
} 

แก้ไข: คุณสามารถทำได้แม้กระทั่งวิธีการขยายและใช้มันเช่นนี้

myObject.HasMethod("SomeMethod");

GetType () จะคืนค่าประเภทรันไทม์หรือไม่ (เช่นไม่ใช่วัตถุ)
Louis Rhys

2
ใช่ GetType () คืนค่าประเภทการทำงานในขณะที่ typeof () จะคืนค่าวัตถุ
Julien

1
ตามเอกสาร GetType () จะส่งคืน "ประเภทรันไทม์ที่แน่นอนของอินสแตนซ์ปัจจุบัน"
tzup

นอกจากนี้วิธีการขยายจะต้องคงที่
เฟรเซอร์

9
ฉันชอบเขียน: objectToCheck.GetType (). GetMethod (methodName)! = null
efirat

85

ผ่านการสะท้อนแสง

 var property = object.GetType().GetProperty("YourProperty")
 property.SetValue(object,some_value,null);

ที่คล้ายกันสำหรับวิธีการ


ดี คุณยังสามารถทำ GetMethod แบบวนซ้ำเพื่อให้ได้คุณสมบัติที่กำหนดไว้อย่างเหมาะสม
Jnr

มีประโยชน์สำหรับการวนซ้ำผ่านรายการที่เชื่อมโยงของตัวควบคุม UI และผู้ปกครองของพวกเขา
Chicowitz

ในมีวิธีเช่นGetType() มันจะกลับอาร์เรย์ของGetProperties() PropertyInfoแต่ฉันจะใช้GetProperties()วิธีการได้อย่างไร
Yogesh Patel

43

มันเป็นคำถามเก่า แต่ฉันเพิ่งพบเจอ Type.GetMethod(string name)จะโยน AmbiguousMatchException หากมีมากกว่าหนึ่งวิธีที่มีชื่อนั้นดังนั้นเราควรจัดการกับกรณีนั้น

public static bool HasMethod(this object objectToCheck, string methodName)
{
    try
    {
        var type = objectToCheck.GetType();
        return type.GetMethod(methodName) != null;
    }
    catch(AmbiguousMatchException)
    {
        // ambiguous means there is more than one result,
        // which means: a method with that name does exist
        return true;
    }
} 

18

มันจะเป็นการดีกว่าหรือที่จะไม่ใช้ประเภทไดนามิกใด ๆ สำหรับสิ่งนี้และให้ชั้นเรียนของคุณใช้อินเทอร์เฟซ จากนั้นคุณสามารถตรวจสอบขณะใช้งานจริงกับวัตถุที่ใช้อินเทอร์เฟซและดังนั้นจึงมีวิธีการที่คาดหวัง (หรือคุณสมบัติ)

public interface IMyInterface
{
   void Somemethod();
}


IMyInterface x = anyObject as IMyInterface;
if( x != null )
{
   x.Somemethod();
}

ฉันคิดว่านี่เป็นวิธีที่ถูกต้องเท่านั้น

สิ่งที่คุณอ้างถึงคือการพิมพ์เป็ดซึ่งมีประโยชน์ในสถานการณ์ที่คุณรู้อยู่แล้วว่าวัตถุนั้นมีวิธีการ แต่คอมไพเลอร์ไม่สามารถตรวจสอบได้ สิ่งนี้มีประโยชน์ในสถานการณ์สมมติ COM interop เช่น (ตรวจสอบนี้บทความ)

หากคุณต้องการผสมผสานการพิมพ์เป็ดกับการสะท้อนกลับฉันคิดว่าคุณพลาดเป้าหมายในการพิมพ์เป็ด


2
จะเกิดอะไรขึ้นถ้าวัตถุสามารถเป็นวัตถุที่ได้รับจากกรอบงาน. NET และฉันไม่สามารถประกาศให้ใช้สิ่งใดได้บ้าง
Louis Rhys

มีปัญหาอะไร ? คุณสามารถตรวจสอบว่า 'วัตถุ' เป็นวัตถุดังกล่าวหรือไม่โดยมีกรอบการทำงาน. NET ในลักษณะเดียวกัน
Frederik Gheysels

ตัวอย่างเช่นคุณต้องการตรวจสอบว่ามีวิธี "เพิ่ม" ในวัตถุ และวัตถุอาจเป็นรายการ <int> หรือคลาสอื่น ๆ ที่ไม่ใช่ IEnumerable
Louis Rhys

3
บางทีคุณควรดูการเขียนสคริปต์ผลิตภัณฑ์ Adobe ด้วย COM การเรียกใช้ฟังก์ชั่นเดียวกันสามารถส่งคืนวัตถุ COM ที่แตกต่างกันอย่างสิ้นเชิงและด้วยการออกแบบ (ของ Adobe) บรรพบุรุษของพวกเขาเท่านั้นที่เป็นวัตถุ นอกจากนี้: นี่เป็นรูปแบบที่พบได้ทั่วไปในภาษาสคริปต์แบบไดนามิกที่ทันสมัย ​​(Python, Javascript, สคริปต์ VB, PHP, Lua ... ฉันสามารถทำต่อไปได้) มันไม่ใช่ข้อผิดพลาดมันเป็นคุณสมบัติ
Tim Keating

5
มันเป็นกลิ่น แต่ถูกสร้างขึ้นโดย microsoft ดูที่ WebControls เช่นปุ่ม, LinkButton, ฯลฯ พวกเขาใช้คุณสมบัติ OnClientClick แต่พูดว่า ListControl และ Panel ไม่ได้ OnClientClick ไม่ได้ถูกกำหนดในอินเทอร์เฟซดังนั้นการสะท้อนจึงเป็นตัวเลือกเดียว
HammerIp
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.