MethodInfo.调用从类到接口的自动转换不工作



我试图通过反射调用类方法。

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

上面这行抛出参数error.."预计IWork…而不是工作……"

如果我写

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

我想知道为什么它不能自动推断和类型转换多态性,或者我完全错了?我们能请个定制班来修水管吗?

请帮助。


编辑

OK。抱歉你们隐瞒了真正的问题。它也适用于Array[],但在List<>…

上抛出错误。

所以我的class是:

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.List 1[IWork]'的对象。

更新后,问题变得很明显。List<Work> 不是 List<IWork>List<T>不协变,如

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

接受List<IWork>的方法可以很好地尝试添加new OtherWork(),这将是一个完全合法的编译时的事情。如果方法传递了一个List<Work>,添加OtherWork将是一个完全非法的运行时的事情,因此语言阻止你在List<IWork>应该传递的地方传递List<Work>

您可能想要做的是让方法接受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();是完全合法的(在编译时),你会得到一个运行时异常。

相关内容

  • 没有找到相关文章

最新更新