web-dev-qa-db-ja.com

Activator.CreateInstanceがコンストラクターを見つけることができません(MissingMethodException)

次のコンストラクターを持つクラスがあります

public DelayCompositeDesigner(DelayComposite CompositeObject)
{
    InitializeComponent();

    compositeObject = CompositeObject;  
}

パラメータのないデフォルトのコンストラクタと一緒に。

次に、インスタンスを作成しようとしていますが、パラメーターがないと機能しません。

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

これは問題なく機能しますが、パラメーターを渡したい場合は機能しません。

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

これにより、MissingMethodExceptionになります。

タイプVialis.LightLink.Controller.Scenarios.Composites.DelayCompositeDesignerのコンストラクターが見つかりませんでした

ここに何かアイデアはありますか?


問題は、構築中にオブジェクトを渡す必要があることです。

CompositeBaseから継承するすべてのタイプをロードするデザイナーがいます。次に、これらはリストに追加され、そこからユーザーはそれらをデザイナーにドラッグできます。そうすると、ドラッグされたインスタンスがデザイナーに追加されます。これらの各クラスには、カスタムプロパティが定義されています。

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

ユーザーがデザイナでアイテムを選択すると、そのタイプのデザイナをロードするためにこれらの属性が調べられます。たとえば、DelayCompositeの場合、ユーザーがDelayCompositeインスタンスの「Delay」プロパティを設定できるようにするラベルとスライダーを持つユーザーコントロールをロードします。

これまでのところ、コンストラクターにパラメーターを渡さなければ、これは正常に機能します。設計者はDelayCompositeDesignerのインスタンスを作成し、それをWPF ContentPresenterのコンテンツプロパティに割り当てます。

ただし、そのデザイナーは、デザイナーで選択したDelayCompositeのプロパティを変更する必要があるため、このインスタンスを渡す必要があります。これが、コンストラクターが次のように見える理由です。

public DelayCompositeDesigner(DelayComposite CompositeObject)
{
    InitializeComponent();

    compositeObject = CompositeObject;
}

提案は大歓迎です


@VolkerK

コードの結果は次のとおりです。

<---- 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 ---->


Leppie、あなたは正しかったです。何らかの理由で、UIアプリケーションでComposites Assemblyを参照していました...これは、実行時にロードしていたので、実行すべきことではありませんでした。次のコードが機能します。

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

ご覧のとおり、コードにはDelayComposite型の知識がありません。

これは現在の問題を解決しますが、私が達成したいことのために多くの新しい問題を紹介します。どちらにしても、ここに返信してくれたすべての人に感謝します。


次のコードについては、複数の人から提案されています。

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)});

結果は同じです。

16
TimothyP

タイプの不一致を扱っていると思います。

アセンブリがさまざまな場所で参照されているか、さまざまなバージョンに対してコンパイルされている可能性があります。

ConstructorInfoを繰り返し処理し、適切なパラメーターに対してparamtype == typeof(DelayComposite)を実行することをお勧めします。

15
leppie

私はあなたの電話が次のようになる必要があると思います:

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

もちろん、それがisそれでない限り、その場合、答えはすぐには明らかではありません。

14
DocMax

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));

Visual Studioの出力ウィンドウに何が印刷されますか?

5
VolkerK

この建設業者に電話したい場合...

public DelayCompositeDesigner(DelayComposite CompositeObject)

...これを使用するだけです:

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

または

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

同様の問題が発生しましたが、問題はコンストラクターの可視性が原因でした。このスタックオーバーフローは私を助けました:

リフレクションを使用した内部クラスのパラメーターを使用したコンストラクターのインスタンス化

1
DevNull

コンストラクターをまったく呼び出さずにオブジェクトのインスタンスを作成する別の方法を発見しました answering SFに関する別の質問。

System.Runtime.Serialization名前空間には、関数FormatterServices.GetUninitializedObject(type)コンストラクターを呼び出さずにオブジェクトを作成します。

Reflectorでその関数を見ると、外部呼び出しを行っていることがわかります。黒魔術が実際にボンネットの下でどのように起こっているのかわかりません。しかし、コンストラクターが呼び出されることはなく、オブジェクトがインスタンス化されたことを私は自分自身に証明しました。

1
Jason Jackson

この問題が発生したとき、Activator.CreateInstanceにプラグインするためにパラメーターリストを返すメソッドを使用していましたが、作成しようとしたオブジェクトのコンストラクターとは異なる数の引数がありました。

0
Mike Cheel

CreateInstanceで次のオーバーロードを使用できます。

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

そしてあなたの場合、それは(私は思う)でしょう:

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

私は問題の解決策を見つけました、私は同じ問題に苦労していました。

これが私のアクティベーターです:

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" });
    }
}
0
Louis Marais