I came later with the same question, found the decision above and decided to add more information and details here regarding how I used reflection and other functions to create interfaces in the source code programmatically. (Skip this first block of code if you don't want to mark the source with custom attributes to generate the code)
For flexibility, I created custom attributes called GenerateInterface and GenerateInterfaceMember (just my own creations) to mark my classes and members for the parts that I want to explicitly export to interfaces (or you can just export all public users by default, whatever), For example, I apply attributes like this to the Store class ...
[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(); }
For user attribute information, see MSDN .
Code Generation Material ...
Note. You can do all of the following without using the custom attributes shown above.
I used reflection to repeat types and members. You just want to capture all the public members in your classes as candidates for creating interfaces.
After receiving instances of System.Reflection.PropertyInfo, .MethodInfo, etc. in System.Type using reflection, I then created a code compilation unit, which is an agnostic of the language and is represented by the System.CodeDom.CodeCompileUnit class , of which MSDN has a good code example - see here. . A code compilation block instance is what you need to compile to describe the source code you want to create, regardless of language.
After creating an instance of CodeCompileUnit, you can pass it to various FCL methods to meet your needs, for example, generate source code, emit MSIL code in memory or on disk, etc. To generate the source code, I used System.CodeDom.Compiler.CodeDomProvider See the MSDN sample in addition to the solution hacked together below ...
CodeDomProvider is where things become language specific - these languages ββare nested in the Microsoft namespace, for example:
using Microsoft.CSharp; // for C
There are several ways to create an instance of CodeDomProvider, for example, the example MSDN code shows the static ".CreateProvider" method:
CodeDomProvider provider = null; // snip... case "CSharp": provider = CodeDomProvider.CreateProvider("CSharp"); break; case "Visual Basic": provider = CodeDomProvider.CreateProvider("VisualBasic"); break;
Alternatively, you can directly create a provider instance
Microsoft.CSharp.CSharpCodeProvider csProvider = new CSharpCodeProvider(); Microsoft.VisualBasic.VBCodeProvider vbProvider = new VBCodeProvider();
Use methods in the provider instance, such as provider.GenerateCodeFromCompileUnit (..) and pass the CodeCompileUnit instance to it. This sample code generates C # source code in an instance of StringBuilder.
// me setting up string capture for my purposes StringBuilder szBuilder = new StringBuilder(); StringWriter writer = new StringWriter(szBuilder); // the key statement - writes c
And there you created the source code.
As a result, I get something similar to the output of the sourceCode string. Good Microsoft adds comments about the auto-generated file - makes you feel more "official".
//------------------------------------------------------------------------------ // <auto-generated> // 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. // </auto-generated> //------------------------------------------------------------------------------ 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); } }
My little disclaimer. There are many ways to generate and emit code. This shows one way to programmatically generate source code. Some methods have overloads and take complex arguments - you will have to look for subtleties in MSDN. Some methods have changed between 1.1, 2.0, etc. Finally, some methods for performing code generation are outdated and have been replaced by alternative means; MSDN notes all of this.
We hope that the code shown here acts as a guide to begin to move forward, creating software interfaces or generating some code in this regard.
Note. This example does not show how to integrate the generated source code with existing code or how to transfer it to MSIL or add it to existing assembly files. The other answers that I see displayed sample designs related to these solutions.