23

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

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ます。

これまでのところ、コンストラクターにパラメーターを渡さなければ、これは正常に機能します。設計者はのインスタンスを作成し、DelayCompositeDesignerそれをWPFのcontentプロパティに割り当てます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アセンブリを参照していました...これは、実行時にロードしていたので、実行すべきことではありませんでした。次のコードが機能します。

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

結果は同じです。

4

10 に答える 10

17

あなたの呼び出しは次のようにする必要があると思います:

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

もちろん、そうでない限り、その場合、答えはすぐにはわかりません.

于 2008-10-16T14:36:37.743 に答える
16

タイプの不一致に対処していると思います。

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

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

于 2008-10-16T15:56:53.820 に答える
6

私は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 の出力ウィンドウには何が出力されますか?

于 2008-10-16T15:17:16.553 に答える
3

このコンストラクターを呼び出したい場合...

public DelayCompositeDesigner(DelayComposite CompositeObject)

...これを使用してください:

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

また

var designer = Activator.CreateInstance<DelayCompositeDesigner>(new DelayComposite(4));
于 2008-10-16T15:06:38.540 に答える
1

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

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

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

于 2008-10-16T14:37:34.823 に答える
1

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

于 2018-08-14T18:33:20.663 に答える
0

問題の解決策を見つけました。同じ問題に苦しんでいました。

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

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" });
    }
}
于 2016-12-14T07:34:57.047 に答える
0

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

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

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

var designer = Activator.CreateInstance(
    typeof(DelayCompositeDesigner), 
    new object[] { new DelayComposite(4) } 
);
于 2008-10-16T14:39:20.670 に答える