توضيح حول كيفية الإعلان عن واجهات التشغيل المتداخل بشكل صحيح

StackOverflow https://stackoverflow.com/questions/1618778

  •  06-07-2019
  •  | 
  •  

سؤال

هذا مجرد سؤال حول كيفية كتابة الكود الخاص بي لاستيراد COM.

إن فهمي للتنفيذ الصحيح لواجهات التشغيل المتداخل هو أن المعايير الرئيسية هي:

  1. يجب أن تتطابق كافة توقيعات الطريقة بطريقة متوافقة
  2. يجب أن تظهر الأساليب بنفس الترتيب تمامًا في واجهة .Net كما تظهر في الواجهة غير المُدارة
  3. عندما ترث الواجهة غير المُدارة من واجهة أخرى غير مُدارة، يجب أن يعلن التطبيق المُدار أولاً عن أعضاء واجهة المستوى الأساسي، بدءًا من الواجهة الأساسية.

سؤالي هو؛ماذا أفعل، فيما يتعلق بالترتيب الذي يظهر به الأعضاء، إذا كانت الواجهة التي أقوم باستيرادها موروثة من واجهة أخرى وتتجاوز/تخفي واحدًا أو أكثر من الأعضاء في الواجهة الأساسية؟أين يذهب إعلان عضو الواجهة؟أولاً، أين أعلنت الواجهة الأساسية ذلك؟أو إزالتها من موضعها الأصلي ووضعها حيث تعلنها الواجهة المشتقة؟

[uuid(31d1c294-1dd2-11b2-be3a-c79230dca297)]
interface BaseComInterface
{
    void method1();
    void method2();
    void method3();
}

[uuid(fab51c92-95c3-4468-b317-7de4d7588254)]
interface DerivedComInterface : BaseComInterface
{
    void method1();
    void method4();
    void method5();
}

الآن للحصول على كود C#:

[Guid("fab51c92-95c3-4468-b317-7de4d7588254"), ComImport, InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IDerivedComInterface
{
    void method1(); // do I remove this one?
    void method2();
    void method3();
    void method1(); // or this one?
    void method4();
    void method5();
}
هل كانت مفيدة؟

المحلول

هل لديك مثال على شخص يفعل هذا فعلا؟على الرغم من أنه من القانوني تمامًا في COM أن يكون لها نفس الاسم لأسلوب ما في واجهة ما وفي واجهة أخرى مشتقة منها، إلا أن ذلك يجعل العمل مع الواجهة المشتقة أمرًا صعبًا أو مستحيلًا في جميع بيئات التطوير تقريبًا.يتضمن ذلك تنفيذ واستدعاء أي كائنات COM بناءً على الواجهة.

لا يوجد شيء مثل التجاوز أو الاختباء في واجهة COM.واجهة COM هي مجرد عقد لكيفية وضع الواجهة الثنائية للكائن في الذاكرة، وأسماء الأساليب في تعريف الواجهة لا معنى لها باستثناء الأدوات.في حالتك، يعد BaseComInterface بـ "vtable" بستة طرق، حيث تتطابق الثلاثة الأولى مع تواقيع طرق IUnknown والثلاثة التالية تتطابق مع تواقيع الطرق الثلاثة التي قدمتها، وكلها بالترتيب الصحيح.من ناحية أخرى، يعد DerivedComInterface بـ "vtable" يتضمن تسع طرق، ومرة ​​أخرى تتطابق التواقيع الثلاثة الأولى مع أساليب IUnknown، وتتطابق الثلاثة التالية مع تواقيع أساليب BaseComInterface، وتتطابق الثلاثة الأخيرة مع الطرق الثلاثة الفريدة لـ DerivedComInterface.أسماء هذه الأساليب غير مهمة باستثناء IDE والأدوات والمترجم الذي يحتاج إلى الأسماء للعثور على مؤشرات "vtable".

لذلك، في الأساس، في C# بالإضافة إلى C وC++ وبعض اللغات الأخرى، من أجل تنفيذ DerivedComInterface، يجب تزيين أحد أسماء الطرق لتمييز فتحة "vtable" الخاصة بها عن الأخرى.

للإجابة على سؤالك - لن تقوم بإزالة أي من الطريقتين نظرًا لأنه يلزم تواجدهما للوفاء بعقد COM:

[Guid("fab51c92-95c3-4468-b317-7de4d7588254"), ComImport,  InterfaceType(ComInterfaceType.InterfaceIsIUnknown)]
public interface IDerivedComInterface
{
    void method1(); 
    void method2();
    void method3();
    void method1_2(); //Decorated to distinguish from base interface method.
    void method4();
    void method5();
}

يتجاهل هذا ما يمكن أن يحدث إذا كانت هذه الواجهات مشتقة من IDispatch بدلاً من IUnknown، وهي فوضى لا أرغب في الدخول فيها.تذكر أيضًا أنه إذا كان idl الخاص بك يعرّف الأساليب بالفعل على أنها إرجاع فارغة، فيجب عليك تزيين أساليب C# باستخدام السمة PreserveSig.

نصائح أخرى

أقترح عليك استخدام تطبيقات أعضاء الواجهة الواضحة لتجنب الصراع.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top