//

C# – Creating an interface for a class automatically

3.10.2021 | 3 minutes of reading time

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

  1. Install the nuget: dotnet add package AutomaticInterface
  2. 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.
  3. Let your class implement the interface, e.g. SomeClass: ISomeClass
  4. 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}
58

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}
34

share post

Likes

0

//

More articles in this subject area\n

Discover exciting further topics and let the codecentric world inspire you.

//

Gemeinsam bessere Projekte umsetzen

Wir helfen Deinem Unternehmen

Du stehst vor einer großen IT-Herausforderung? Wir sorgen für eine maßgeschneiderte Unterstützung. Informiere dich jetzt.

Hilf uns, noch besser zu werden.

Wir sind immer auf der Suche nach neuen Talenten. Auch für dich ist die passende Stelle dabei.