如何仅从接口和方法名称调用方法?

How to invoke method only from interface and method name?

在我的程序中,我们引用了另一个程序集,而那个程序集中肯定有一个实现实例。所以我们想在 运行 时间调用它的方法。我们知道接口和方法名,但是实现实例名还不确定。如何仅从接口和方法名称调用方法?

Type outerInterface = Assembly.LoadAssembly("AnotherAssemblyFile").GetTypes()
     .Single(f => f.Name == "ISample" && f.IsInterface == true);
Object instance = Activator.CreateInstance(outerInterface);
MethodInfo mi = outerInterface.GetMethod("SampleMethod");
var result = mi.Invoke(instance, new object[]{"you will see me"});

抛出异常:

An unhandled exception of type 'System.MissingMethodException' occurred in mscorlib.dll

Additional information: Cannot create an instance of an interface.

引用的汇编代码在这里:

namespace AnotherAssembly
{
    public interface ISample
    {
        string SampleMethod(string name);
    }

    public class Sample : ISample
    {
        public string SampleMethod(string name)
        {
            return string.Format("{0}--{1}", name, "Alexsanda");
        }
    }
}

但是反射部分不工作,我不确定如何才能让它工作得很好。

编辑:我不清楚实例名,只知道接口名和方法名。但我知道肯定有一个来自该程序集接口的实现class。

您的错误信息非常清楚:您不能创建接口实例。想象一下,如果您写...

var x = new ISample()

... 在正常代码中。这完全没有意义

错误源于这些代码行...

Type outerInterface = Assembly.LoadAssembly("AnotherAssemblyFile").GetTypes()
     .Single(f => f.Name == "ISample" && f.IsInterface == true);
Object instance = Activator.CreateInstance(outerInterface);

... 在上面的清单中,您找到接口 本身 然后尝试实例化它。

您真正想要做的是找到一个实现接口的类型并实例化它...

Type type = Assembly.Load("AnotherAssembly")
    .GetTypes()
    .Single(t => t.GetInterfaces().Contains(typeof(ISample)));
ISample instance = (ISample) Activator.CreateInstance(type);
string result = instance.SampleMethod("test");

... 请注意我如何 cast 将实例 ISample - 这消除了调用 GetMethod.

的需要

如果您还没有对程序集的引用,您可以这样做:

Type[] types = Assembly
    .Load("AnotherAssembly")
    .GetTypes();
Type sampleInterface = types
    .Single(f => f.Name == "ISample" && f.IsInterface == true);
Type type = types
    .Single(t => t.GetInterfaces().Contains(sampleInterface));
object instance = Activator.CreateInstance(type);
MethodInfo method = type.GetMethod("SampleMethod");
string result = (string) method.Invoke(instance, new object[] { "you will see me" });

您无法实例化一个接口,但您可以找到 class 实现它:

Assembly assembly = Assembly.LoadAssembly("AnotherAssemblyFile");
Type[] assemblyTypes = assembly.GetTypes();

Type ISampleType = assemblyTypes.GetType("NameSpace.ISample");

Type sampleType = assemblyTypes.Single(type => 
                  (type != ISampleType) && ISampleType.IsAssignableFrom(type));

object instance = Activator.CreateInstance(sampleType);
MethodInfo mi = sampleType .GetMethod("SampleMethod");
var result = mi.Invoke(instance, new object[]{"you will see me"});

你不能创建接口类型的实例,因为接口只是一个API,它是一个契约定义,没有别的。实际上,如果你尝试实例化接口,你会得到异常:

System.MissingMethodException: Cannot create an instance of an interface.

因此您需要获取实现您的接口的类型并实例化该类型的实例:

var anotherAssemblyTypes = Assembly.LoadAssembly("AnotherAssemblyFile").GetTypes();
// get interface type
Type outerInterface = anotherAssemblyTypes
                        .Single(t => t.Name == "ISample" && t.IsInterface);
// find class which implements it
Type outerClass = anotherAssemblyTypes
                        .Single(t => !t.IsInterface && outerInterface.IsAssignableFrom(t));
// instantiate class
dynamic obj = Activator.CreateInstance(outerClass);
string result = obj.SampleMethod("Bob");

当然你不必在这里使用动态对象。我用它只是为了测试 SampleMethod 被调用。