Skip to content

Examples

beakona edited this page Feb 27, 2021 · 20 revisions

Simple scenario - inferred interface type

Manually written source:

interface IPrintable
{
   void Print();
}

public partial class Person : IPrintable
{
   [BeaKona.AutoInterface]
   private readonly IPrintable aspect1 = new PersonPrinterV1();
}

Auto-generated accompanying source:

partial class Person
{
   void IPrintable.Print() => this.aspect1.Print();
}

Explicitly defined interface type

Manually written source:

interface IPrintable
{
   void Print();
}

public partial class Person : IPrintable
{
   [BeaKona.AutoInterface(typeof(IPrintable))]
   private readonly PersonPrinterV1 aspect1 = new PersonPrinterV1();
}

Auto-generated accompanying source:

partial class Person
{
   void IPrintable.Print() => ((IPrintable)this.aspect1).Print();
}

Single interface - multiple backers

Manually written source:

interface IPrintable
{
   void Print();
}

public partial class Person : IPrintable
{
   [BeaKona.AutoInterface]
   private readonly IPrintable aspect1 = new PersonPrinterPart1();

   [BeaKona.AutoInterface]
   private readonly IPrintable aspect2 = new PersonPrinterPart2();
}

Auto-generated accompanying source:

partial class Person
{
   void IPrintable.Print()
   {
      this.aspect1.Print();
      this.aspect2.Print();
   }
}

Multiple interfaces

Manually written source:

interface IPrintable
{
   void Print();
}

interface IScannable
{
   void Scan();
}

public partial class Person : IPrintable, IScannable
{
   [BeaKona.AutoInterface(typeof(IPrintable))]
   [BeaKona.AutoInterface(typeof(IScannable))]
   private readonly Printer aspect1 = new Printer();
}

Auto-generated accompanying source:

partial class Person
{
   void IPrintable.Print() => ((IPrintable)this.aspect1).Print();
   void IScannable.Scan() => ((IScannable)this.aspect1).Scan();
}

Resolving appropriate reference

Manually written source:

public interface IPrintable
{
   void Print();
}

public partial class Person : IPrintable
{
   [BeaKona.AutoInterface]
   private IPrintable Aspect1
   {
      get
      {
         return condition ? myPersonPrinterV1 : myPersonPrinterV2;
      }
   }
}

Auto-generated accompanying source:

partial class Person
{
   void IPrintable.Print() => this.Aspect1.Print();
}

Custom member implementation

Manually written source:

public interface IPrintable
{
   void Print();
   void Align();
}

public partial class Person : IPrintable
{
   [BeaKona.AutoInterface]
   private readonly IPrintable aspect1 = new PersonPrinterV1();

   void IPrintable.Print()
   {
      //custom implementation which will prevent auto-generation
   }
}

Auto-generated accompanying source:

partial class Person
{
   void IPrintable.Align() => this.aspect1.Align();
}

Methods, properties, indexers, events

Manually written source:

interface ITest
{
   int Age { get; }
   int this[in int a, int b = 5] { get; set; }

   event EventHandler<EventArgs> Done;

   void Method1(int a, out int b, ref int c, in int d, params int[] e);
   void Method2(int a = 1);
}

public partial class Person : ITest
{
   [BeaKona.AutoInterface]
   private readonly ITest aspect1 = new PersonTest();
}

Auto-generated accompanying source:

partial class Person
{
   int ITest.Age => this.aspect1.Age;

   int ITest.this[in int a, int b]
   {
      get => this.aspect1[in a, b];
      set => this.aspect1[in a, b] = value;
   }

   event System.EventHandler<System.EventArgs> ITest.Done
   {
      add => this.aspect1.Done += value;
      remove => this.aspect1.Done -= value;
   }

   void ITest.Method1(int a, out int b, ref int c, in int d, params int[] e) => this.aspect1.Method1(a, out b, ref c, in d, e);

   void ITest.Method2(int a = 1) => this.aspect1.Method2(a);
}

Class, record, struct

Manually written source:

public interface IPrintable
{
   void Print();
}

public partial record PersonR : IPrintable
{
   [BeaKona.AutoInterface]
   private readonly IPrintable aspect1 = new RecordPrinter();
}

public partial class PersonC : IPrintable
{
   [BeaKona.AutoInterface]
   private readonly IPrintable aspect1 = new ClassPrinter();
}

public partial struct PersonS : IPrintable
{
   public PersonS(IPrintable aspect1) => this.aspect1 = aspect1;

   [BeaKona.AutoInterface]
   private readonly IPrintable aspect1;
}

Auto-generated accompanying source:

partial record PersonR
{
   void IPrintable.Print() => this.aspect1.Print();
}
partial class PersonC
{
   void IPrintable.Print() => this.aspect1.Print();
}
partial struct PersonS
{
   void IPrintable.Print() => this.aspect1.Print();
}

Template

Manually written source:

interface IPrintable
{
   void Print();
}

public partial class Person : IPrintable
{
   [BeaKona.AutoInterface(TemplateLanguage = "scriban", TemplateBody = "customizable template definition")]
   private readonly IPrintable? aspect1 = null;
}

Auto-generated accompanying source:

partial class Person
{
   customizable template definition
}

More complete scriban template can be found [here](https://github.com/beakona/AutoInterface/wiki/Template).

Async

Manually written source:

interface ITest
{
   Task Method1Async();
   Task<int> Method2Async();

   ValueTask Method3Async();
   ValueTask<int> Method4Async();
}

public partial class Person : ITest
{
   [BeaKona.AutoInterface]
   private readonly ITest aspect1 = new Test();

   [BeaKona.AutoInterface]
   private readonly ITest aspect2 = new Test();
}

Auto-generated accompanying source:

partial class Person
{
   async Task ITest.Method1Async()
   {
      await this.aspect1.Method1Async();
      await this.aspect2.Method1Async();
   }

   async Task<int> ITest.Method2Async()
   {
      await this.aspect1.Method2Async();
      return await this.aspect2.Method2Async();
   }

   async ValueTask ITest.Method3Async()
   {
      await this.aspect1.Method3Async();
      await this.aspect2.Method3Async();
   }

   async ValueTask<int> ITest.Method4Async()
   {
      await this.aspect1.Method4Async();
      return await this.aspect2.Method4Async();
   }
}

Value tuples

Manually written source:

interface IPrintable
{
   void Print((int x, int y) position);
}

public partial class Person : IPrintable
{
   [BeaKona.AutoInterface]
   private readonly IPrintable aspect1 = new PersonPrinterV1();
}

Auto-generated accompanying source:

partial class Person
{
   void IPrintable.Print((int x, int y) position) => this.aspect1.Print(position);
}

Type casting

Manually written source:

interface IPrintable
{
   void Print();
}

interface IPrintableEx : IPrintable
{
   void PrintEx();
}

public partial class Person : IPrintable
{
   [BeaKona.AutoInterface(typeof(IPrintable))]
   private readonly IPrintableEx aspect1 = new PersonPrinterV1();
}

Auto-generated accompanying source:

partial class Person
{
   void IPrintable.Print() => ((IPrintable)this.aspect1).Print();
}

Conflicting type argument name

Manually written source:

interface ITest
{
   T F<T>(IEnumerable<T> elements);
}

public partial class Person<T> : ITest
{
   [BeaKona.AutoInterface]
   private readonly ITest aspect1 = new Test();
}

Auto-generated accompanying source:

partial class Person<T>
{
   T1 ITest.F<T1>(IEnumerable<T1> elements) => this.aspect1.F<T1>(elements);
}

Assembly alias

Manually written source:

extern alias alias1;

public partial class Person : alias1::Some.IPrintable
{
   [BeaKona.AutoInterface]
   private readonly alias1::Some.IPrintable aspect1 = new PersonPrinterV1();
}

Auto-generated accompanying source:

extern alias alias1;

partial class Person
{
   void alias1::Some.IPrintable.Print() => this.aspect1.Print();
}

Nested types

Manually written source:

namespace Scope
{
   public class Wrapper
   {
      public interface IPrintable
      {
         void Print();
      }
   }
}

public partial class Person : Scope.Wrapper.IPrintable
{
   [BeaKona.AutoInterface]
   private readonly Scope.Wrapper.IPrintable aspect1 = new PersonPrinterV1();
}

Auto-generated accompanying source:

partial class Person
{
   void Scope.Wrapper.IPrintable.Print() => this.aspect1.Print();
}

Verbatim names

Manually written source:

interface IPrintable
{
   void Print();
}

public partial class Person : IPrintable
{
   [BeaKona.AutoInterface]
   private readonly IPrintable @object = new PersonPrinterV1();
}

Auto-generated accompanying source:

partial class Person
{
   void IPrintable.Print() => this.@object.Print();
}

Clone this wiki locally