1

リフレクションを介してクラスメソッドを呼び出そうとしています。

public class A
{
    public string B(IWork WorkToDo)
    {
        return WorkToDo.ToString();
    }
}

クラス「Work」は「IWork」を継承しています。

Type type = Type.GetType("A");

MethodInfo MI = type.GetMethod("B");

object X = MI.Invoke(Activator.CreateInstance(type), new object[] { new Work() });

上記の行は引数エラーをスローします。「Workの代わりにIWorkが必要です。」

私が書いたら

object X = MI.Invoke(Activator.CreateInstance(type), new object[] { (new Work() as IWork) });

できます。

ポリモーフィズムを自動的に推測して型キャストできない理由を知りたいのですが、それともすべて間違っているのでしょうか。配管を行うためのカスタムバインダークラスを作成できますか?

助けてください。


編集

わかった。本当の問題を隠してくれてすみません。上記で機能します。Array[]でも機能しますが、List<>..でエラーをスローします。

したがって、私のクラスは次のようになります。

public class A
{
    public string B(List<IWork> WorkToDo)
    {
        return WorkToDo.ToString();
    }
}

Type type = Type.GetType("A");

MethodInfo MI = type.GetMethod("B");
List<Work> WL = new List<Work>(); WL.Add(new Work());
object X = MI.Invoke(Activator.CreateInstance(type), new object[] { WL });

エラーは次のとおりです。

タイプ'System.Collections.Generic.List1 1[Work]' cannot be converted to type 'System.Collections.Generic.List[IWork]'のオブジェクト。

4

1 に答える 1

2

アップデートすると、問題が明らかになります。List<Work> ではありません List<IWork>List<T>与えられたように、共変ではありません

interface IWork { }
class Work : IWork { } 
class OtherWork : IWork { } 

受け入れるメソッドは、List<IWork>を追加しようとする可能性が非常に高くnew OtherWork()、それは完全に合法的なコンパイル時のことです。メソッドが渡された場合、List<Work>OtherWorkを追加することは、実行時に完全に違法なことになるため、言語によって、期待されるList<Work>場所を渡すことができなくなりますList<IWork>

あなたがしたいと思うかもしれないことはIEnumerable<IWork>あなたがあなたのを渡すことを可能にするであろうメソッドacceptを持っていることですList<Work>IEnumerable<T>は共変であり(C#4の場合)、読み取り専用であるため、シーケンスへの書き込みや追加は行われません。

完全な実例:

namespace Foo
{
    public class A
    {
        // note the change to the signature
        public string B(IEnumerable<IWork> workToDo)
        {
            return workToDo.ToString();
        }

        static void Main()
        {
            var type = Type.GetType("Foo.A");
            var info = type.GetMethod("B");
            var list = new List<Work>();
            var x = info.Invoke(Activator.CreateInstance(type), new [] { list });
        }
    }

    public interface IWork { }
    public class Work : IWork { }
}

配列に対して機能する理由については、配列の分散が壊れています。これにより、コンパイル時に実行時に完全に危険になる可能性のあるものが可能になります。同じ問題が実行時に存在する可能性があります。を受け入れるメソッドがIWork[] arrayあり、を渡すWork[]と、この場合、コンパイラーでそれを実行できるようになります。ただし、(コンパイル時に)言うことは完全に合法でarray[0] = new OtherWork();あり、実行時例外が発生します。

于 2011-12-30T15:39:10.307 に答える