Skip to main content

AutoInterface by Black White Yoshi

NuGet / site data

Nuget GitHub last commit GitHub Repo stars

Details

Info

info

Name: AutoInterface

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.

Author: Black White Yoshi

NuGet: https://www.nuget.org/packages/AutoInterface/

You can find more details at https://github.com/BlackWhiteYoshi/AutoInterface

Source: https://github.com/BlackWhiteYoshi/AutoInterface

Original Readme

note

AutoInterface

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:

Examples

AutoInterfaceAttribute on struct

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

AutoInterfaceAttribute with all kinds of members

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

AutoInterfaceAttribute with explicit interface specifier

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

multiple AutoInterfaceAttributes on same class

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

AutoInterfaceAttribute with summary documentation

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();
}

AutoInterfaceAttribute with generic class

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);
}

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();
}
}
}
  • StaticMembers

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();
}
  • Access Modifier

When you want to set the visibility of a specific member, you can decorate it with a [AutoInterfaceVisibility...] attribute.
There are 5 different Visibility attribute:

  • [AutoInterfaceVisibilityPublic]
  • [AutoInterfaceVisibilityInternal]
  • [AutoInterfaceVisibilityProtected]
  • [AutoInterfaceVisibilityProtectedInternal]
  • [AutoInterfaceVisibilityPrivateProtected]
using AutoInterfaceAttributes;

[AutoInterface]
public sealed class Example : IExample {
[AutoInterfaceVisibilityPublic]
public void PublicMethod() { }

[AutoInterfaceVisibilityInternal]
void IExample.InternalMethod() { }

[AutoInterfaceVisibilityProtected]
void IExample.ProtectedMethod() { }

[AutoInterfaceVisibilityProtectedInternal]
void IExample.ProtectedInternalMethod() { }

[AutoInterfaceVisibilityPrivateProtected]
void IExample.PrivateProtectedMethod() { }
}
// <auto-generated/>
#pragma warning disable
#nullable enable annotations


using AutoInterfaceAttributes;

public partial interface IExample {
[AutoInterfaceVisibilityPublic]
public void PublicMethod();

[AutoInterfaceVisibilityInternal]
internal void InternalMethod();

[AutoInterfaceVisibilityProtected]
protected void ProtectedMethod();

[AutoInterfaceVisibilityProtectedInternal]
protected internal void ProtectedInternalMethod();

[AutoInterfaceVisibilityPrivateProtected]
private protected void PrivateProtectedMethod();
}

Note:
The access modifiers private and file are not possible, because private members needs an implementation and file members would not be visible to the outside.

  • IgnoreAutoInterfaceAttribute

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

Disable Attribute Generation

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.

Remarks

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.

About

note

generating interface from a class

How to use

Example (source csproj, source files)

This is the CSharp Project that references AutoInterface

<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net9.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>

<PropertyGroup>
<EmitCompilerGeneratedFiles>true</EmitCompilerGeneratedFiles>
<CompilerGeneratedFilesOutputPath>$(BaseIntermediateOutputPath)\GX</CompilerGeneratedFilesOutputPath>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="AutoInterface" Version="2.4.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
</Project>

Generated Files

Those are taken from $(BaseIntermediateOutputPath)\GX

// <auto-generated/>
#pragma warning disable
#nullable enable annotations


#if !AUTOINTERFACE_EXCLUDE_ATTRIBUTES

using System;

namespace AutoInterfaceAttributes;

/// <summary>
/// Generates an interface for the decorated class/struct.
/// </summary>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Struct, AllowMultiple = true)]
[System.CodeDom.Compiler.GeneratedCodeAttribute("AutoInterface", "2.4.0")]
internal sealed class AutoInterfaceAttribute : Attribute {
/// <summary>
/// <para>The name of the generated interface.</para>
/// <para>Default is "I{ClassName}"</para>
/// </summary>
public string Name { get; init; }

/// <summary>
/// <para>The modifier(s) for the interface.</para>
/// <para>Deault is "public partial"</para>
/// </summary>
public string Modifier { get; init; }

/// <summary>
/// <para>The namespace declaration for the interface.</para>
/// <para>If empty string, no namespace directive will be used (global namespace).<br />
/// Default (if not present) it will be mapped to the same namespace as the namespace of the class/struct.</para>
/// </summary>
public string Namespace { get; init; }

/// <summary>
/// <para>interface inheritance: Name(s) of interfaces this interface will inherit.</para>
/// <para>Default is Array.Empty</para>
/// </summary>
public Type[] Inheritance { get; init; }

/// <summary>
/// <para>
/// The Classes, structs or interfaces containing the generated interface.<br />
/// e.g. ["public sealed partial class Example"] will wrap the interface with that expression.
/// </para>
/// <para>Default is Array.Empty</para>
/// </summary>
public string[] Nested { get; init; }

/// <summary>
/// <para>If enabled, static members get accepted and are generating "static abstract" members.</para>
/// <para>Default is false</para>
/// </summary>
public bool StaticMembers { get; init; }
}

#endif

Useful

Download Example (.NET C#)

Share AutoInterface

https://ignatandrei.github.io/RSCG_Examples/v2/docs/AutoInterface

In the same category (Interface) - 12 other generators

Biwen.AutoClassGen

CopyCat

Farskeptic.AutoCompose

MakeInterface.Generator

Matryoshki

Minerals.AutoInterfaces

NetAutomaticInterface

ProxyGen

Roozie.AutoInterface

RSCG_CompositeProvider

rscg_Interface_to_null_object

RSCG_Static