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

时间:2015-08-06 07:48:16

标签: c# reflection

在我的程序中,我们引用了另一个程序集,并且该程序集中有一个实现实例。所以我们想在运行时调用它的方法。我们已经知道接口和方法名称,但实现实例名称并不一定。我怎么只能从接口和方法名称调用方法?

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

但反射部分不起作用,我不知道如何让它运作良好。

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

3 个答案:

答案 0 :(得分:2)

您的错误消息非常明确:您无法创建接口实例。想象一下,如果你写了......

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

... 请注意我ISample实例的cast - 这样就无需调用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" });

答案 1 :(得分:1)

您无法实例化接口,但可以找到实现它的类:

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

答案 2 :(得分:1)

您无法创建接口类型的实例,因为接口只是一个API,它是一个合同定义而不是其他任何东西。实际上,如果您尝试实例化界面,您将获得异常:

  

System.MissingMethodException:无法创建的实例   接口

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

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。