AutoInterface is a source generator that generates an interface based on your class/struct.
Basically, you write your class and get the corresponding interface for free.
using AutoInterfaceAttributes;
[AutoInterface]
public class Example : IExample {
public int Number { get; private set; }
public Example() {
ResetNumber();
}
/// <summary>
/// some method description
/// </summary>
public int AddToNumber(int increase) {
Number += increase;
return Number;
}
private void ResetNumber() => Number = 0;
}
// <auto-generated/>
#pragma warning disable
#nullable enable annotations
using AutoInterfaceAttributes;
public partial interface IExample {
int Number { get; }
/// <summary>
/// some method description
/// </summary>
int AddToNumber(int increase);
}
AutoInterface supports:
- classes, records and structs
- all members (Method, Property, Indexer, Event)
- also explicit Interface members
- multiple attributes on same class
- summary of class/struct and members
- generic
- parameters for
using AutoInterfaceAttributes;
[AutoInterface]
public struct Point {
public int X { get; private set; }
public int Y { get; private set; }
public Point(int x, int y) => (X, Y) = (x, y);
}
// <auto-generated/>
#pragma warning disable
#nullable enable annotations
using AutoInterfaceAttributes;
public partial interface IPoint {
int X { get; }
int Y { get; }
}
using AutoInterfaceAttributes;
[AutoInterface]
public sealed class FullExample {
public void SomeMethod() { }
public int SomeProperty { get; init; }
public int this[int i] => i;
public event Action? someEvent;
public event Action SomeEvent { add { } remove { } }
}
// <auto-generated/>
#pragma warning disable
#nullable enable annotations
using AutoInterfaceAttributes;
public partial interface IFullExample {
void SomeMethod();
int SomeProperty { get; init; }
int this[int i] { get; }
event Action? someEvent;
event Action SomeEvent;
}
using AutoInterfaceAttributes;
[AutoInterface]
public sealed class ExplicitExample : IExplicitExample {
void IExplicitExample.SomeMethod() { }
int IExplicitExample.SomeProperty { get; init; }
int IExplicitExample.this[int i] => i;
event Action IExplicitExample.SomeEvent { add { } remove { } }
}
// <auto-generated/>
#pragma warning disable
#nullable enable annotations
using AutoInterfaceAttributes;
public partial interface IExplicitExample {
void SomeMethod();
int SomeProperty { get; init; }
int this[int i] { get; }
event Action SomeEvent;
}
using AutoInterfaceAttributes;
[AutoInterface(Name = "IMultipleExample1")]
[AutoInterface(Name = "IMultipleExample2")]
public sealed class MultipleExample : IMultipleExample1, IMultipleExample2 {
public void SomeMethod() { }
int IMultipleExample1.PropertyFirst { get; set; }
string IMultipleExample2.PropertySecond { get; set; }
}
// <auto-generated/>
#pragma warning disable
#nullable enable annotations
using AutoInterfaceAttributes;
public partial interface IMultipleExample1 {
void SomeMethod();
int PropertyFirst { get; set; }
}
...
// <auto-generated/>
#pragma warning disable
#nullable enable annotations
using AutoInterfaceAttributes;
public partial interface IMultipleExample2 {
void SomeMethod();
string PropertySecond { get; set; }
}
using AutoInterfaceAttributes;
/// <summary>
/// my class description
/// </summary>
[AutoInterface]
public sealed class SummaryExample {
/// <summary>
/// some method description
/// </summary>
public void SomeMethod() { }
}
// <auto-generated/>
#pragma warning disable
#nullable enable annotations
using AutoInterfaceAttributes;
/// <summary>
/// my class description
/// </summary>
public partial interface ISummaryExample {
/// <summary>
/// some method description
/// </summary>
void SomeMethod();
}
using AutoInterfaceAttributes;
[AutoInterface]
public sealed class GenericExample<T> {
public T Identity(T parameter) => parameter;
}
// <auto-generated/>
#pragma warning disable
#nullable enable annotations
using AutoInterfaceAttributes;
public partial interface IGenericExample<T> {
T Identity(T parameter);
}
Type: string
Default: $"I{ClassName}"
If you want another name for your interface, put it here.
using AutoInterfaceAttributes;
[AutoInterface(Name = "NewName")]
public sealed class Example;
// <auto-generated/>
#pragma warning disable
#nullable enable annotations
using AutoInterfaceAttributes;
public partial interface NewName {}
Type: string
Default: "public partial"
If you want another visible modifier or make the interface non-partial or unsafe, you can do this here.
using AutoInterfaceAttributes;
[AutoInterface(Modifier = "internal")]
public sealed class Example;
// <auto-generated/>
#pragma warning disable
#nullable enable annotations
using AutoInterfaceAttributes;
internal interface IExample {}
Type: string
Default: $"{ClassNamespace}"
When the generated interface should live in a specific namespace, you can specify it here.
For global namespace, use an empty string.
using AutoInterfaceAttributes;
namespace MyApp.Core;
[AutoInterface(Namespace = "MyApp.Utils")]
public sealed class Example;
// <auto-generated/>
#pragma warning disable
#nullable enable annotations
using AutoInterfaceAttributes;
namespace MyApp.Utils;
public partial interface IExample {}
Type: Type[]
Default: []
If the generated interface should inherit from one or more other interfaces, you can list them here.
using AutoInterfaceAttributes;
[AutoInterface(Inheritance = [typeof(ICore)])]
public sealed class Example;
public partial interface ICore { ... }
// <auto-generated/>
#pragma warning disable
#nullable enable annotations
using AutoInterfaceAttributes;
public partial interface IExample : ICore {}
Type: string[]
Default: []
When the interface should be nested inside other classes, structs or interfaces, declare them here.
using AutoInterfaceAttributes;
[AutoInterface(Nested = ["public partial class MyWrapper", "public partial interface OuterInterface"])]
public sealed class Example {
public void SomeMethod() { }
}
// <auto-generated/>
#pragma warning disable
#nullable enable annotations
using AutoInterfaceAttributes;
public partial class MyWrapper {
public partial interface OuterInterface {
public partial interface IExample {
void SomeMethod();
}
}
}
Type: bool
Default: false
Normally, static members are just ignored.
However, an interface can contain static members as a "static abstract" member.
To accept static members to generate "static abstract" members, set this flag to true.
using AutoInterfaceAttributes;
[AutoInterface(StaticMembers = true)]
public sealed class Example {
public static void SomeMethod() { }
}
// <auto-generated/>
#pragma warning disable
#nullable enable annotations
using AutoInterfaceAttributes;
public partial interface IExample {
static abstract void SomeMethod();
}
When you want a specific member to be ignored by the generator, you can decorate it with [IgnoreAutoInterface].
using AutoInterfaceAttributes;
[AutoInterface]
public sealed class Example {
[IgnoreAutoInterface]
public void SomeMethod() { }
}
// <auto-generated/>
#pragma warning disable
#nullable enable annotations
using AutoInterfaceAttributes;
public partial interface IExample {}
You can disable the generation of the attributes by defining a constant for your compilation:
<PropertyGroup>
<DefineConstants>AUTOINTERFACE_EXCLUDE_ATTRIBUTES</DefineConstants>
</PropertyGroup>
This functionality is specific for the use case when you have a project referencing another project, both projects using this generator and you have InternalsVisibleTo enabled. In that case you have the attributes defined twice in your referencing project and you get a warning about that. By defining this constant in your referencing project, you prevent one generation, so the attributes are only defined once in the referenced project.
Using-statements will always be placed on the top, so using not fully-qualified using-statements might cause compile errors.
using AutoInterfaceAttributes;
namespace System.Collections {
using Generic; // <-- refers to "System.Collections.Generic"
[AutoInterface]
public sealed class Example;
}
// ...
// <auto-generated/>
#pragma warning disable
#nullable enable annotations
using Generic; // <-- refers to "Generic"
using AutoInterfaceAttributes;
public partial interface IExample {}
You also should not use not fully-qualified using-statements in the first place, because they can be ambiguous. By introducing an additional namespace, the referring of a not fully-qualified using-statement might change and your application breaks at unrelated places. Just put your using statements at the top.