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

上面的行抛出参数错误..“预期 IWork...而不是 Work..”

如果我写

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

有用。

我想知道为什么它不能自动推断和类型转换多态性还是我完全错了?我们可以有一个自定义的 Binder 类来做管道吗?

请帮忙。


编辑

好的。抱歉,伙计们隐瞒了真正的问题。它适用于上述..也适用于 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.List 1[Work]' cannot be converted to type 'System.Collections.Generic.List1[IWork]' 类型的对象。

4

1 回答 1

2

随着您的更新,问题变得显而易见。List<Work> 不是一个 List<IWork>List<T>不是协变的,如给定的

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

接受的方法List<IWork>很可能会尝试添加new OtherWork(),这将是完全合法的编译时要做的事情。如果该方法是通过 a 传递的List<Work>,那么添加 OtherWork 将是完全非法的运行时事情,因此该语言会阻止您传递预期的List<Work>位置。List<IWork>

您可能想要做的是让方法接受IEnumerable<IWork>,这将允许您通过您的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 回答