The last few years have seen a huge proliferation of interfaces for C# classes. These interfaces are very useful for DI, testing and mocking. But they come at a cost: while extracting an interface is fairly easy, you now have to keep interface and class in sync. Especially in an evolving project, this can quickly become annoying. Change a parameter on the class? Edit the interface, too! Change to class-doc? Edit the interface, too. This is tedious, and smaller things like parameter names and documentation get out of sync quickly.
Luckily, C# Source Generators offer the ability to automatically generate these interfaces for us. I even wrote a post about this topic last year, but the birth of our second child prevented me from finishing my idea. Finally, I was able to complete the code and publish it as a NuGet Package: AutomaticInterface .
AutomaticInterface takes care of creating an interface for a class – it automatically copies all public properties, methods, events and the documentation to the interface. You can use it like a normal interface and every change to your class will be picked up by the interface in the next build.
How to use it
- Install the nuget:
dotnet add package AutomaticInterface - Create an attribute with the name
[GenerateAutomaticInterface]. You can just copy the minimal code from the repo . It’s the easiest way to get that attribute because you cannot reference any code from the analyzer package. - Let your class implement the interface, e.g.
SomeClass: ISomeClass - Build the solution, the interface should now be available.
1using AutomaticInterfaceAttribute;
2using System;
3
4namespace AutomaticInterfaceExample
5{
6 /// <summary>
7 /// Class Documentation will be copied
8 /// </summary>
9 [GenerateAutomaticInterface] // you need to create an attribute with exactly this name in your solution. You cannot reference code from the analyzer.
10 class DemoClass: IDemoClass // You Interface will get the Name I+classname, here IDemoclass.
11 // Generics, including constraints are allowed, too. E.g. MyClass<T> where T: class
12 {
13
14 /// <summary>
15 /// Property Documentation will be copied
16 /// </summary>
17 public string Hello { get; set; } // included, get and set are copied to the interface when public
18
19 public string OnlyGet { get; } // included, get and set are copied to the interface when public
20
21 /// <summary>
22 /// Method Documentation will be copied
23 /// </summary>
24 public string AMethod(string x, string y) // included
25 {
26 return BMethod(x,y);
27 }
28
29 private string BMethod(string x, string y) // ignored because not public
30 {
31 return x + y;
32 }
33
34 public static string StaticProperty => "abc"; // static property, ignored
35
36 public static string StaticMethod() // static method, ignored
37 {
38 return "static" + DateTime.Now;
39 }
40
41 /// <summary>
42 /// event Documentation will be copied
43 /// </summary>
44
45 public event EventHandler ShapeChanged; // included
46
47 private event EventHandler ShapeChanged2; // ignored because not public
48
49 private readonly int[] arr = new int[100];
50
51 public int this[int index] // currently ignored
52 {
53 get => arr[index];
54 set => arr[index] = value;
55 }
56 }
57}
This will create this interface:
1using System.CodeDom.Compiler;
2using AutomaticInterfaceAttribute;
3using System;
4
5/// <summary>
6/// Result of the generator
7/// </summary>
8namespace AutomaticInterfaceExample
9{
10 /// <summary>
11 /// Bla bla
12 /// </summary>
13 [GeneratedCode("AutomaticInterface", "")]
14 public partial interface IDemoClass
15 {
16 /// <summary>
17 /// Property Documentation will be copied
18 /// </summary>
19 string Hello { get; set; }
20
21 string OnlyGet { get; }
22
23 /// <summary>
24 /// Method Documentation will be copied
25 /// </summary>
26 string AMethod(string x, string y);
27
28 /// <summary>
29 /// event Documentation will be copied
30 /// </summary>
31 event System.EventHandler ShapeChanged;
32 }
33}
More articles in this subject area
Discover exciting further topics and let the codecentric world inspire you.
Blog author
Christian Sauer
Do you still have questions? Just send me a message.
Do you still have questions? Just send me a message.