لا يمكن لـ Activator.CreateInstance العثور على المنشئ (MissingMethodException)

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

سؤال

لدي فصل يحتوي على المنشئ التالي

public DelayCompositeDesigner(DelayComposite CompositeObject)
{
    InitializeComponent();

    compositeObject = CompositeObject;  
}

مع مُنشئ افتراضي بدون معلمات.

بعد ذلك، أحاول إنشاء مثيل، ولكنه يعمل فقط بدون معلمات:

var designer = Activator.CreateInstance(designerAttribute.Designer);

يعمل هذا بشكل جيد، ولكن إذا أردت تمرير المعلمات، فلن يحدث ذلك:

var designer = Activator.CreateInstance(designerAttribute.Designer, new DelayComposite(4));

وينتج عن هذا MissingMethodException:

Constructor voor type Vialis.LightLink.Controller.Scenarios.Composites.DelayCompositeDesigner was not found

أي أفكار هنا؟


المشكلة هي أنني أحتاج حقًا إلى تمرير جسم أثناء البناء.

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

[CompositeMetaData("Delay","Sets the delay between commands",1)]
[CompositeDesigner(typeof(DelayCompositeDesigner))]
public class DelayComposite : CompositeBase
{
}

عندما يحدد المستخدم عنصرًا في المصمم، فإنه ينظر إلى هذه السمات من أجل تحميل مصمم لهذا النوع.على سبيل المثال، في حالة DelayComposite سيتم تحميل عنصر تحكم المستخدم الذي يحتوي على تسمية وشريط تمرير يسمح للمستخدم بتعيين خاصية "التأخير" الخاصة DelayComposite مثال.

يعمل هذا بشكل جيد حتى الآن إذا لم أقوم بتمرير أي معلمات إلى المُنشئ.يقوم المصمم بإنشاء مثيل لـ DelayCompositeDesigner ويعينها لخاصية محتوى WPF ContentPresenter.

ولكن بما أن المصمم يحتاج إلى تعديل خصائص المحدد DelayCompositeفي المصمم، لا بد لي من تمرير هذه الحالة إليه.لهذا السبب يبدو المنشئ كذبة:

public DelayCompositeDesigner(DelayComposite CompositeObject)
{
    InitializeComponent();

    compositeObject = CompositeObject;
}

الاقتراحات هي موضع ترحيب


@فولكرك

نتيجة الكود الخاص بك هي:

<---- foo Vialis.LightLink.Controller.Scenarios.Composites.DelayCompositeDesignerVoid .ctor() Vialis.LightLink.Controller.Scenarios.Composites.DelayCompositeDesignerVoid .ctor(Vialis.LightLink.Controller.Scenarios.Composites.DelayComposite) param:Vialis.LightLink.Controller.Scenarios.Composites.DelayComposite foo ---->


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

object composite = Activator.CreateInstance(item.CompositType,(byte)205);
                    var designer = Activator.CreateInstance(designerAttribute.Designer, composite);

كما ترون فإن الكود ليس لديه معرفة بـ DelayComposite يكتب.

This solves the current problem, but introduces many new ones for what I want to achieve, either way thank you and thank you to everyone who has replied here.


أما بالنسبة للكود التالي، فقد اقترحه عدة أشخاص:

var designer = Activator.CreateInstance(
    designerAttribute.Designer, 
    new object[] { new DelayComposite(4) } 
);

ال Activator.CreateInstance لديه توقيع يبدو كالتالي:

Activator.CreateInstance(Type type, params object[] obj)

لذلك يجب أن يقبل الكود الخاص بي، ولكن سأحاول الكود المقترح

تحديث:

لقد جربت هذا كما هو مقترح:

var designer = Activator.CreateInstance(designerAttribute.Designer, new object[] { new DelayComposite(4)});

والنتيجة هي نفسها.

هل كانت مفيدة؟

المحلول

أعتقد أنك تتعامل مع عدم تطابق النوع.

من المحتمل أن تتم الإشارة إلى التجميع في أماكن مختلفة، أو أنه تم تجميعه مقابل إصدارات مختلفة.

أقترح عليك التكرار من خلال ConstructorInfo's والقيام بـ paramtype == typeof(DelayComposite) على المعلمة المناسبة.

نصائح أخرى

أعتقد أن مكالمتك يجب أن تكون:

var designer = Activator.CreateInstance(designerAttribute.Designer, new object[] { new DelayComposite(4) });

ما لم يكن ذلك بالطبع يكون ذلك، وفي هذه الحالة لا يكون الجواب واضحًا على الفور.

على الرغم من أنني أكره تصحيح الأخطاء مثل printf ...

public static void foo(Type t, params object[] p)
{
    System.Diagnostics.Debug.WriteLine("<---- foo");
    foreach(System.Reflection.ConstructorInfo ci in t.GetConstructors())
    {
        System.Diagnostics.Debug.WriteLine(t.FullName + ci.ToString());
    }
    foreach (object o in p)
    {
        System.Diagnostics.Debug.WriteLine("param:" + o.GetType().FullName);
    }
    System.Diagnostics.Debug.WriteLine("foo ---->");
}
// ...
foo(designerAttribute.Designer, new DelayComposite(4));
var designer = Activator.CreateInstance(designerAttribute.Designer, new DelayComposite(4));

ما الذي يطبعه ذلك في نافذة إخراج الاستوديو المرئي؟

إذا كنت تريد استدعاء هذا المقاول ...

public DelayCompositeDesigner(DelayComposite CompositeObject)

...فقط استخدم هذا:

var designer = Activator.CreateInstance(typeof(DelayCompositeDesigner), new DelayComposite(4));

أو

var designer = Activator.CreateInstance<DelayCompositeDesigner>(new DelayComposite(4));

لقد واجهت مشكلة مماثلة، ولكن مشكلتي كانت بسبب رؤية المُنشئ.ساعدني تجاوز سعة المكدس هذا:

إنشاء مثيل للمنشئ باستخدام المعلمات في فئة داخلية مع الانعكاس

لقد اكتشفت طريقة أخرى لإنشاء مثيل لكائن دون استدعاء المُنشئ على الإطلاق الرد سؤال آخر على SF.

في ال System.Runtime.Serialization مساحة الاسم هناك وظيفة FormatterServices.GetUninitializedObject(نوع) سيؤدي ذلك إلى إنشاء كائن دون استدعاء المنشئ.

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

يمكنك استخدام التحميل الزائد التالي على CreateInstance:

public static Object CreateInstance(
    Type type,
    Object[] args
)

وفي حالتك سيكون (على ما أعتقد):

var designer = Activator.CreateInstance(
    typeof(DelayCompositeDesigner), 
    new object[] { new DelayComposite(4) } 
);

لقد وجدت حلاً للمشكلة، كنت أعاني من نفس المشكلة.

هنا هو المنشط الخاص بي:

private void LoadTask(FileInfo dll)
    {
        Assembly assembly = Assembly.LoadFrom(dll.FullName);

        foreach (Type type in assembly.GetTypes())
        {
            var hasInterface = type.GetInterface("ITask") != null;

            if (type.IsClass && hasInterface)
            {
                var instance = Activator.CreateInstance(type, _proxy, _context);
                _tasks.Add(type.Name, (ITask)instance);
            }
        }
    }

وهنا فصلي الذي يجب تنشيطه، لاحظ أنه كان عليّ تغيير معلمات المُنشئ إلى كائنات، وهي الطريقة الوحيدة التي يمكنني من خلالها تشغيله.

public class CalculateDowntimeTask : Task<CalculateDowntimeTask>
{
    public CalculateDowntimeTask(object proxy, object context) : 
        base((TaskServiceClient)proxy, (TaskDataDataContext)context) { }

    public override void Execute()
    {
        LogMessage(new TaskMessage() { Message = "Testing" });
        BroadcastMessage(new TaskMessage() { Message = "Testing" });
    }
}

عندما واجهت هذه المشكلة، كنت أستخدم طريقة تقوم بإرجاع قائمة المعلمات للتوصيل بـ Activator.CreateInstance وكان لها عدد مختلف من الوسائط عن مُنشئ الكائن الذي كنت أحاول إنشائه.

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