【问题标题】:check if class from assembly contans all methods as in interface检查程序集中的类是否包含接口中的所有方法
【发布时间】:2012-03-11 19:04:52
【问题描述】:

我有在运行时加载的自定义程序集。

此时我有代码可以加载 dll 并可以创建新的对象实例和执行方法。

如何验证该类是否实现了我在接口中定义的所有功能。

(我正在尝试创建具有不同操作的插件系统,可以在运行时打开,以提供不同的行为)。

我的代码应该是这样的主程序:

public Interface IArticleManager{
 void SetMenuId(int MenuId);
 void SetMenu(string name);
 void SetContent(string content);
 bool Save();
}

我的类库(断开连接可以从解决方案中看到)

public class XmlArticle{
    public void SetMenuId(int MenuId){
       //some implementation
     }
     public void SetMenu(string name){
       //some implementation
}
     public void SetContent(string content){
       //some implementation
}
    public bool Save(){
}
}


public class SqlArticle{
    public void SetMenuId(int MenuId){
       //some implementation
     }
     public void SetMenu(string name){
       //some implementation
}
     public void SetContent(string content){
       //some implementation
}
    public bool Save(){
}
}

【问题讨论】:

  • 我就是想不通。为什么定义一个接口,却不从它继承具体的实现?
  • 你的类需要实现你的接口。这就是接口的目的,所以你不需要检查类是否具有所有必需的方法......
  • @DaniilNovikov:因为我的界面存在于主程序中,并且该类不一定必须有一个,但我确实想将它与我存在于主程序中的界面相匹配,以确保兼容性.
  • @Lloyd:不。他的类没有实现任何接口...
  • 在单独的程序集中移动您的界面。将此程序集引用到主程序和需要它的地方。在具体实现中继承这个接口。

标签: c# reflection


【解决方案1】:

基本上,换种说法,您想检查一个类是否定义了接口的契约,即使它没有显式实现该接口?

这是非常重要的,也是一个非常非常糟糕的主意。相反,我强烈建议您将插件接口重构为合同程序集,并从您的插件和主应用程序中引用该程序集。然后,您的插件可以实际实现合同,并且您可以得到编译器保护,以免弄乱实现。

如果你坚持走这条路,但是:

var interfaceType = typeof(IArticleManager);
var targetType = typeof(SqlArticle);
foreach(var member in interfaceType.GetMembers())
{
    var targetMember = targetType.GetMember(member.Name);
    // compare the arguments, generic constraints, etc here
}

我会把它留给你来做比较,因为老实说,它需要大量的编码。您需要检查该成员是属性、事件或方法、泛型还是非泛型等。

【讨论】:

  • +1 表示您的答案的第二部分,-1 表示向他展示了一种完全按照他的要求去做的方法,尽管这很可能会在以后烧毁他。
  • @DanielHilgarth 这样做有一些正当的理由——我实际上做过一次。我正在创建一个消息总线,并希望用户能够插入他们自己的接口来代替我的 IConsume 接口,所以我只要求他们提供一个具有相同签名的接口。这并不漂亮,但是如果您必须在程序集之间进行松散耦合且没有编译时引用,这是唯一的方法。
  • 请注意,我所做的与 OP 想要做的区别在于我硬编码了接口规范,而 OP 似乎希望能够验证任何接口。跨度>
  • @DavidPfeffer:感谢您的意见,非常感谢
【解决方案2】:

您需要做的似乎是将接口移动到一个单独的程序集中,该程序集仅包含“主程序”和动态加载的 DLL 都可以访问的接口。

因此,为了创建一个动态加载的 DLL 并期望它在您的基础架构中工作,作者首先需要引用接口程序集,然后实现提供的接口。

【讨论】:

    【解决方案3】:

    检查一个类是否实现了接口中的所有方法是没有用的,除非它实际上实现了接口本身 - 它具有相同方法名称的事实最终只是巧合。

    要检查对象实例是否实现了接口:

    if (obj is IArticleManager)
    

    这将返回true。

    但是,如果你想实际使用接口的方法,它会更好(更少的转换):

    IArticleManager manager = obj as IArticleManager;  
    if (manager != null)  
    { do stuff }
    

    【讨论】:

      【解决方案4】:

      当你不能在任何地方使用IArticleManager时,它的目的是什么?

      除此之外,如果我们接受您想要创建一个非常松散的插件系统,您可以强制每个插件程序集只有一个公共类,然后通过反射实例化该类,并通过反射调用它的方法,同时传递适当的论据。

      与每个插件或其他外部代码一样,您应该验证输出并保护您的应用免受错误(即捕获并记录插件异常)。这也将处理无效插件(没有所需签名的插件)

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2020-02-04
        • 1970-01-01
        • 2012-11-03
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-04-20
        相关资源
        最近更新 更多