c# - استدعاء الأسلوب العام مع وسيطة النوع المعروفة فقط في وقت التنفيذ



linq generics (1)

هذا السؤال لديه بالفعل إجابة هنا:

تصحيح:

بالطبع لا يبدو شفرتي الحقيقية بهذا الشكل. حاولت أن أكتب رمز شبه زائف لجعلها أكثر وضوحا من whay أردت أن تفعل.

يبدو وكأنه مجرد افسدت الامور بدلا من ذلك.

لذا ، ما أود فعله في الواقع هو:

Method<Interface1>();
Method<Interface2>();
Method<Interface3>();
...

حسنا ... اعتقدت أنه ربما يمكنني تحويلها إلى حلقة باستخدام التفكير. لذا فإن السؤال هو: كيف أفعل ذلك. لدي معرفة ضحلة جدا من التفكير. حتى أمثلة التعليمات البرمجية ستكون رائعة.

السيناريو يبدو كالتالي:

public void Method<T>() where T : class
{}
public void AnotherMethod()
{
    Assembly assembly = Assembly.GetExecutingAssembly();

    var interfaces = from i in assembly.GetTypes()
    where i.Namespace == "MyNamespace.Interface" // only interfaces stored here
    select i;

    foreach(var i in interfaces)
    {
        Method<i>(); // Get compile error here!
    }



المشاركة الأصلية:

مرحبا!

أحاول التكرار خلال جميع الواجهات في مساحة اسم وإرسالها كوسيطات إلى طريقة عامة مثل:

public void Method<T>() where T : class
{}
public void AnotherMethod()
{
    Assembly assembly = Assembly.GetExecutingAssembly();

    var interfaces = from i in assembly.GetTypes()
    where i.Namespace == "MyNamespace.Interface" // only interfaces stored here
    select i;

    foreach(var interface in interfaces)
    {
        Method<interface>(); // Get compile error here!
    }
}

الخطأ الذي أحصل عليه هو "اسم النوع المتوقع ، ولكن تم العثور على اسم المتغير المحلي". إذا حاولت

...
    foreach(var interface in interfaces)
    {
        Method<interface.MakeGenericType()>(); // Still get compile error here!
    }
}

أحصل على "لا يمكن تطبيق عامل التشغيل" <"إلى مجموعة أساليب التشغيل" 'و "System.Type" "أي فكرة حول كيفية التغلب على هذه المشكلة؟


تحرير: حسنا ، حان الوقت لبرمجة قصيرة ولكن كاملة. الجواب الأساسي كما كان من قبل:

  • العثور على طريقة عامة "مفتوحة" مع Type.GetMethod
  • جعلها عامة باستخدام MakeGenericMethod
  • استدعيها مع Invoke

وهنا بعض نماذج التعليمة البرمجية. لاحظ أني قمت بتغيير تعبير طلب البحث إلى تدوين النقطة - ليس هناك أي نقطة في استخدام تعبير استعلام عندما يكون لديك في الأساس جملة حيث.

using System;
using System.Linq;
using System.Reflection;

namespace Interfaces
{
    interface IFoo {}
    interface IBar {}
    interface IBaz {}
}

public class Test
{
    public static void CallMe<T>()
    {
        Console.WriteLine("typeof(T): {0}", typeof(T));
    }

    static void Main()
    {
        MethodInfo method = typeof(Test).GetMethod("CallMe");

        var types = typeof(Test).Assembly.GetTypes()
                                .Where(t => t.Namespace == "Interfaces");

        foreach (Type type in types)
        {
            MethodInfo genericMethod = method.MakeGenericMethod(type);
            genericMethod.Invoke(null, null); // No target, no arguments
        }
    }
}

الجواب الأصلي

دعونا نترك المشاكل الواضحة المتمثلة في استدعاء "واجهة" متغيرة لتبدأ بها.

عليك أن تسميها بالتأمل. الهدف من علم الوراثة هو وضع المزيد من التدقيق في وقت الترجمة . أنت لا تعرف ما هو نوع في وقت التجميع - وبالتالي يجب عليك استخدام الأدوية البديلة.

الحصول على الطريقة العامة ، واستدعاء MakeGenericMethod عليها ، ثم استدعاء ذلك.

هل واجهت الواجهة نفسها بشكل عام؟ أسأل لأنك تقوم بـ MakeGenericType عليها ، ولكن لا تمر في أي نوع من الوسيطات ... هل تحاول الاتصال

Method<MyNamespace.Interface<string>>(); // (Or whatever instead of string)

أو

Method<MyNamespace.Interface>();

إذا كان هذا الأخير ، فأنت تحتاج فقط إلى استدعاء MakeGenericMethod - وليس MakeGenericType.





reflection