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

Posted

技术标签:

【中文标题】如何仅从接口和方法名称调用方法?【英文标题】:How to invoke method only from interface and method name? 【发布时间】:2015-08-06 07:48:16 【问题描述】:

在我的程序中,我们引用了另一个程序集,并且该程序集中肯定有一个实现实例。所以我们想在运行时调用它的方法。我们知道接口和方法的名字,但是具体的实现实例名就不一定了。我如何只能从接口和方法名称调用方法?

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

但是反射部分不起作用,我不确定如何使它正常工作。

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

【问题讨论】:

请提供异常详情 您不能创建接口实例。您应该创建实现接口的类的实例。 IE。 Sample 在你的情况下 Activator.CreateInstance(outerInterface);?您正在尝试创建接口的实例?你应该寻找它的实现。 【参考方案1】:

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

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

【讨论】:

嗨,我没有直接引用另一个程序集,我只是从文件中动态加载它,我如何使用 ISample 类型,接口名称只是一个字符串类型。谢谢 @BesLey 我更新了我的答案。这是你想要的吗? @BesLey 太棒了。如果此答案回答了您的问题,请考虑将其标记为已接受。谢谢。【参考方案2】:

您不能创建接口类型的实例,因为接口只是一个 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 是否被调用。

【讨论】:

"SampleMehod" 是一个字符串变量,但在你的最后一行,你直接使用它,似乎我无法使用动态样式。 @BesLey 这就是为什么我只写了关于我的测试使用动态的注释的确切原因:“我用它只是为了测试 SampleMethod 被调用” 太好了,我明白了。这是一个很好的解决方案。谢谢【参考方案3】:

你不能实例化一个接口,但你可以找到实现它的类:

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

【讨论】:

您好,我使用了您的示例代码,...typeof(ISampleType)...,找不到类型或命名空间名称“ISampleType”(您是否缺少 using 指令或程序集引用?)。 它几乎可以工作,但仍需要修复。因为有两种类型匹配它。这样可以正常工作。类型 sampleType = anotherAssemblyTypes .Single(type => !type.IsInterface && outerInterface.IsAssignableFrom(type)); @BesLey 另一个匹配的类型必须是 ISampleType 本身:) 我已经修复了代码。

以上是关于如何仅从接口和方法名称调用方法?的主要内容,如果未能解决你的问题,请参考以下文章

java 当一个接口被多个类继承时 如何知道是调用的哪个类的实现

.NET Web 方法没有被仅从 javascript 页面调用

dubbo接口调用总结

如何通过实例方法名字的字符串调用方法?

如何防止从特定类调用公共方法

类与接口方法重载解析