当前位置:  开发笔记 > 编程语言 > 正文

有没有办法以编程方式提取接口?

如何解决《有没有办法以编程方式提取接口?》经验,为你挑选了2个好方法。

假设我有一个像这样的.NET类:

public class Person {
    public string Name { get; set; }
    public int Id { get; set; }
}

Visual Studio有一个名为Extract Interface的漂亮的重构工具,它将提取一个IPerson接口并Person实现它.有没有办法从Visual Studio外部以编程方式执行此操作?如果不能以编程方式完成,我甚至会使用shell脚本.

[编辑]实际上,我最多有50个类,每个类都有相互依赖.

反思会起作用,但它会在整个事物中引入另一个皱纹.这些类已经由生成xsd.exe.所以,如果我理解正确,我需要采取的步骤是:

    从中生成类xsd.exe.

    动态编译类,以便我可以使用反射.

    反映它们,发出接口,并编辑原始类以实现所述接口.

一般来说,我赞成放弃接口并直接使用类,但出于各种原因我不能.



1> John K..:

我后来遇到了同样的问题,找到了上面接受的解决方案,并决定在这里添加更多信息和细节,关于我如何使用反射和其他功能以编程方式在源代码中生成接口.(如果您不关心使用自定义属性标记源代码,请跳过此第一个代码块)

为了灵活性,我创建了名为GenerateInterfaceGenerateInterfaceMember的自定义属性(只是我自己的创建)来标记我的类和成员我想要显式导出到接口的部分(或者你可以默认导出所有公共成员,无论你喜欢什么).例如,我将这样的属性应用于Store类......

[GenerateInterface(InterfaceName="IStore", NamespaceName="Com.Example.GenerationTest")]
class Store : BusinessObject {
    string _name;

    [GenerateInterfaceMember]
    public event EventHandler handler;

    internal Store(IDomain domain, string name)
        : base(domain) {
        _name = name;
    }

    [GenerateInterfaceMember]
    public string GetSomething(int a, int b, Random r, Store s) {
        throw new NotImplementedException();
    }
//etc...

有关自定义属性的信息,请参阅MSDN.

代码生成的东西......

注意:您无需使用上面显示的自定义属性即可执行以下所有操作.

我使用反射来迭代类型和成员.您只想抓住类中的所有公共成员作为创建接口的候选者.

在System.Type上使用反射获取System.Reflection.PropertyInfo,.MethodInfo等实例后,我创建了一个与语言无关的代码编译单元,由System.CodeDom.CodeCompileUnit类表示,其中MSDN有很好的例子代码 - 在这里看到它..代码编译单元实例是您需要构建的,用于描述您希望以与语言无关的方式生成的源代码.

一旦创建了CodeCompileUnit实例,就可以将它提供给各种FCL方法以满足您的需求,比如生成源代码,在内存或磁盘中发出MSIL代码等.要生成源代码我使用System.CodeDom.Compiler.CodeDomProvider查看MSDN样本除了下面的攻击解决方案...

CodeDomProvider是特定于语言的地方 - 这些语言嵌套在Microsoft命名空间下,例如:

using Microsoft.CSharp; // for C#
using Microsoft.VisualBasic; // for VB.NET

有两种方法可以创建CodeDomProvider实例,比如这里的MSDN代码示例显示了一个静态方法'.CreateProvider':

CodeDomProvider provider = null;
// snip...
case "CSharp":
   provider = CodeDomProvider.CreateProvider("CSharp");
   break;
case "Visual Basic":
   provider = CodeDomProvider.CreateProvider("VisualBasic");
   break;

或者,您可以直接实例化提供程序

Microsoft.CSharp.CSharpCodeProvider csProvider = new CSharpCodeProvider();
Microsoft.VisualBasic.VBCodeProvider vbProvider = new VBCodeProvider();

在provider.GenerateCodeFromCompileUnit(..)等提供程序实例上使用方法,并将CodeCompileUnit实例提供给它.此示例代码为StringBuilder实例生成C#源代码.

// me setting up string capture for my purposes
StringBuilder szBuilder = new StringBuilder();
StringWriter writer = new StringWriter(szBuilder);

// the key statement - writes c# code to StringBuilder using provider instance and compile unit instance
csProvider.GenerateCodeFromCompileUnit(compileUnit, writer, new CodeGeneratorOptions());

// solidifying the generated C# code into one string
string sourceCode = szBuilder.ToString(); 
// can write this string to a file, etc....

你已经生成了源代码.

在输出sourceCode字符串时,我最终得到了这样的东西.很好的微软预先设置了关于自动生成文件的评论 - 让它感觉更"官方".

//------------------------------------------------------------------------------
// 
//     This code was generated by a tool.
//     Runtime Version:2.0.50727.4200
//
//     Changes to this file may cause incorrect behavior and will be lost if
//     the code is regenerated.
// 
//------------------------------------------------------------------------------

namespace Com.Example.GenerationTest {
    using System;
    using Com.Example.BusinessCore;


    public interface IStore {

        string Name {
            get;
            set;
        }

         event System.EventHandler handler;

        string GetSomething(int a, int b, System.Random r, Store s);
    }
}

我的小免责声明:有很多方法可以生成和发出代码.这里显示的是以编程方式生成源代码的一种方法.有些方法有重载并且需要复杂的参数 - 你必须在MSDN中查找错综复杂的内容.有些方法在1.1,2.0等之间发生了变化.最后,一些完成代码生成的方法已经过时,已经被替代方法所取代; MSDN记录了所有这些事情.

希望这里显示的代码可以作为指导,开始以编程方式生成接口,或生成任何类型的代码.

注意:此示例未显示如何将生成的源代码与现有代码集成,或如何将其发布到MSIL或附加到现有的汇编文件 - 我看到的其他答案显示与这些解决方案相关的示例.



2> joel.neely..:

总之:反思.

编写一些带有类对象的代码,反映其公共方法,并编写一个文本文件,这是该类实现的接口的定义,这是非常可行的.

但是,确定WHICH方法属于某个接口(例如,一个类可以实现多个,对吧?)并将正确的符号添加到类的源代码中需要做更多的工作.

推荐阅读
地之南_816
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有