Skip to content
beakona edited this page Nov 30, 2023 · 20 revisions

Simple scenario - inferred interface type

Manually written source:

interfaceIPrintable{voidPrint();}publicpartialclassPerson:IPrintable{[BeaKona.AutoInterface]privatereadonlyIPrintableaspect1=newPersonPrinterV1();}

Auto-generated accompanying source:

partialclassPerson{voidIPrintable.Print()=>this.aspect1.Print();}

Explicitly defined interface type

Manually written source:

interfaceIPrintable{voidPrint();}publicpartialclassPerson:IPrintable{[BeaKona.AutoInterface(typeof(IPrintable))]privatereadonlyPersonPrinterV1aspect1=newPersonPrinterV1();}

Auto-generated accompanying source:

partialclassPerson{voidIPrintable.Print()=>((IPrintable)this.aspect1).Print();}

Ad-hoc adapter pattern - part1

In this example PersonPrinterV1 does not implement IPrintable but does have all members that are required by that interface.

Manually written source:

interfaceIPrintable{voidPrint();}classPersonPrinterV1{voidPrint(){ ...}}publicpartialclassPerson{[BeaKona.AutoInterface(typeof(IPrintable))]privatereadonlyPersonPrinterV1aspect1=newPersonPrinterV1();}

Auto-generated accompanying source:

partialclassPerson:IPrintable{voidIPrintable.Print()=>this.aspect1.Print();}

Ad-hoc adapter pattern - part2

In this example PersonPrinterV1 does not implement IPrintable but does have some members that are required by that interface but not all.

Manually written source:

interfaceIPrintable{voidPrint();voidPrint2();}classPersonPrinterV1{voidPrint(){ ...}}publicpartialclassPerson{[BeaKona.AutoInterface(typeof(IPrintable),AllowMissingMembers=true,MemberMatch=BeaKona.MemberMatchTypes.Public)]privatereadonlyPersonPrinterV1aspect1=newPersonPrinterV1();publicvoidPrint2(){ ...}}

Auto-generated accompanying source:

partialclassPerson:IPrintable{voidIPrintable.Print()=>this.aspect1.Print();}

Recursive interface types

Manually written source:

interfaceIPrintable{voidPrint();}interfaceIPrintableEx:IPrintable{voidPrintEx();}publicpartialclassPerson{[BeaKona.AutoInterface(typeof(IPrintableEx),IncludeBaseInterfaces=true)]privatereadonlyPersonPrinterV1aspect1=newPersonPrinterV1();}

Auto-generated accompanying source:

partialclassPerson:IPrintableEx,IPrintable{voidIPrintable.Print()=>((IPrintable)this.aspect1).Print();voidIPrintableEx.PrintEx()=>((IPrintableEx)this.aspect1).PrintEx();}

Single interface - multiple backers

Manually written source:

interfaceIPrintable{voidPrint();}publicpartialclassPerson:IPrintable{[BeaKona.AutoInterface]privatereadonlyIPrintableaspect1=newPersonPrinterPart1();[BeaKona.AutoInterface]privatereadonlyIPrintableaspect2=newPersonPrinterPart2();}

Auto-generated accompanying source:

partialclassPerson{voidIPrintable.Print(){this.aspect1.Print();this.aspect2.Print();}}

Multiple interfaces

Manually written source:

interfaceIPrintable{voidPrint();}interfaceIScannable{voidScan();}publicpartialclassPerson:IPrintable,IScannable{[BeaKona.AutoInterface(typeof(IPrintable))][BeaKona.AutoInterface(typeof(IScannable))]privatereadonlyPrinteraspect1=newPrinter();}

Auto-generated accompanying source:

partialclassPerson{voidIPrintable.Print()=>((IPrintable)this.aspect1).Print();voidIScannable.Scan()=>((IScannable)this.aspect1).Scan();}

Resolving appropriate reference

Manually written source:

publicinterfaceIPrintable{voidPrint();}publicpartialclassPerson:IPrintable{[BeaKona.AutoInterface]privateIPrintableAspect1{get{returncondition?myPersonPrinterV1:myPersonPrinterV2;}}}

Auto-generated accompanying source:

partialclassPerson{voidIPrintable.Print()=>this.Aspect1.Print();}

Custom member implementation - part1

Manually written source:

publicinterfaceIPrintable{voidPrint();voidAlign();}publicpartialclassPerson:IPrintable{[BeaKona.AutoInterface]privatereadonlyIPrintableaspect1=newPersonPrinterV1();voidIPrintable.Print(){//custom implementation which will prevent auto-generation}}

Auto-generated accompanying source:

partialclassPerson{voidIPrintable.Align()=>this.aspect1.Align();}

Custom member implementation - part2

Manually written source:

publicinterfaceIPrintable{voidPrint();voidAlign();}publicpartialclassPerson{[BeaKona.AutoInterface(MemberMatch=BeaKona.MemberMatchTypes.Public)]privatereadonlyIPrintableaspect1=newPersonPrinterV1();publicvoidPrint(){//custom implementation which will prevent auto-generation}}

Auto-generated accompanying source:

partialclassPerson{voidIPrintable.Align()=>this.aspect1.Align();}

Methods, properties, indexers, events

Manually written source:

interfaceITest{intAge{get;}intthis[ininta,intb=5]{get;set;}eventEventHandler<EventArgs>Done;voidMethod1(inta,outintb,refintc,inintd,paramsint[]e);voidMethod2(inta=1);}publicpartialclassPerson:ITest{[BeaKona.AutoInterface]privatereadonlyITestaspect1=newPersonTest();}

Auto-generated accompanying source:

partialclassPerson{intITest.Age=>this.aspect1.Age;intITest.this[ininta,intb]{get=>this.aspect1[ina,b];set=>this.aspect1[ina,b]=value;}eventSystem.EventHandler<System.EventArgs>ITest.Done{add=>this.aspect1.Done+=value;remove=>this.aspect1.Done-=value;}voidITest.Method1(inta,outintb,refintc,inintd,paramsint[]e)=>this.aspect1.Method1(a,outb,refc,ind,e);voidITest.Method2(inta=1)=>this.aspect1.Method2(a);}

Class, record, struct

Manually written source:

publicinterfaceIPrintable{voidPrint();}publicpartialrecordPersonR:IPrintable{[BeaKona.AutoInterface]privatereadonlyIPrintableaspect1=newRecordPrinter();}publicpartialclassPersonC:IPrintable{[BeaKona.AutoInterface]privatereadonlyIPrintableaspect1=newClassPrinter();}publicpartialstructPersonS:IPrintable{publicPersonS(IPrintableaspect1)=>this.aspect1=aspect1;[BeaKona.AutoInterface]privatereadonlyIPrintableaspect1;}

Auto-generated accompanying source:

partialrecordPersonR{voidIPrintable.Print()=>this.aspect1.Print();}partialclassPersonC{voidIPrintable.Print()=>this.aspect1.Print();}partialstructPersonS{voidIPrintable.Print()=>this.aspect1.Print();}

Full template from string

Manually written source:

interfaceIPrintable{voidPrint();}publicpartialclassPerson:IPrintable{[BeaKona.AutoInterface(TemplateLanguage="scriban",TemplateBody="customizable template definition")]privatereadonlyIPrintable?aspect1=null;}

Auto-generated accompanying source:

partialclassPerson{customizabletemplate definition
}

More complete scriban template can be found on template page.

Full template from file

Manually written source:

interfaceIPrintable{voidPrint();}publicpartialclassPerson:IPrintable{// add file mytemplate.scriban in your VS project// and set it's build action to: 'C# analyzer additional file'[BeaKona.AutoInterface(TemplateFileName="mytemplate.scriban")]privatereadonlyIPrintable?aspect1=null;}

Auto-generated accompanying source:

partialclassPerson{customizabletemplate definition
}

Partial template

Partial template can be defined inline (from string) or from file.

Manually written source:

interfaceIPrintable{voidPrint();}publicpartialclassPerson:IPrintable{[BeaKona.AutoInterface][BeaKona.AutoInterfaceTemplate(BeaKona.AutoInterfaceTargets.Method,Filter="regex member name matcher",Body="customizable template1 definition")][BeaKona.AutoInterfaceTemplate(BeaKona.AutoInterfaceTargets.Method,Filter="another name matcher",Body="template2")][BeaKona.AutoInterfaceTemplate(BeaKona.AutoInterfaceTargets.PropertyGetter,Filter="propery1",Body="template3")]privatereadonlyIPrintable?aspect1=null;}

Auto-generated accompanying source:

partialclassPerson{//member is generated using default template because//no custom implementation is matchedvoidIPrintable.Print()=>this.aspect1.Print();}

Enum AutoInterfaceTargets definition:

[Flags]publicenumAutoInterfaceTargets:byte{Method=0x01,PropertyGetter=0x02,PropertySetter=0x04,IndexerGetter=0x08,IndexerSetter=0x10,EventAdder=0x20,EventRemover=0x40,Property=PropertyGetter|PropertySetter,Indexer=IndexerGetter|IndexerSetter,Event=EventAdder|EventRemover,Getter=PropertyGetter|IndexerGetter,Setter=PropertySetter|IndexerSetter,All=Method|Property|Indexer|Event,}

Async

Manually written source:

interfaceITest{TaskMethod1Async();Task<int>Method2Async();ValueTaskMethod3Async();ValueTask<int>Method4Async();}publicpartialclassPerson:ITest{[BeaKona.AutoInterface]privatereadonlyITestaspect1=newTest();[BeaKona.AutoInterface]privatereadonlyITestaspect2=newTest();}

Auto-generated accompanying source:

partialclassPerson{asyncTaskITest.Method1Async(){awaitthis.aspect1.Method1Async();awaitthis.aspect2.Method1Async();}asyncTask<int>ITest.Method2Async(){awaitthis.aspect1.Method2Async();returnawaitthis.aspect2.Method2Async();}asyncValueTaskITest.Method3Async(){awaitthis.aspect1.Method3Async();awaitthis.aspect2.Method3Async();}asyncValueTask<int>ITest.Method4Async(){awaitthis.aspect1.Method4Async();returnawaitthis.aspect2.Method4Async();}}

Value tuples

Manually written source:

interfaceIPrintable{voidPrint((intx,inty)position);}publicpartialclassPerson:IPrintable{[BeaKona.AutoInterface]privatereadonlyIPrintableaspect1=newPersonPrinterV1();}

Auto-generated accompanying source:

partialclassPerson{voidIPrintable.Print((intx,inty)position)=>this.aspect1.Print(position);}

Type casting

Manually written source:

interfaceIPrintable{voidPrint();}interfaceIPrintableEx:IPrintable{voidPrintEx();}publicpartialclassPerson:IPrintable{[BeaKona.AutoInterface(typeof(IPrintable))]privatereadonlyIPrintableExaspect1=newPersonPrinterV1();}

Auto-generated accompanying source:

partialclassPerson{voidIPrintable.Print()=>((IPrintable)this.aspect1).Print();}

Conflicting type argument name

Manually written source:

interfaceITest{TF<T>(IEnumerable<T>elements);}publicpartialclassPerson<T>:ITest{[BeaKona.AutoInterface]privatereadonlyITestaspect1=newTest();}

Auto-generated accompanying source:

partialclassPerson<T>{T1ITest.F<T1>(IEnumerable<T1>elements)=>this.aspect1.F<T1>(elements);}

Assembly alias

Manually written source:

externaliasalias1;publicpartialclassPerson:alias1::Some.IPrintable{[BeaKona.AutoInterface]privatereadonlyalias1::Some.IPrintableaspect1=newPersonPrinterV1();}

Auto-generated accompanying source:

externaliasalias1;partialclassPerson{voidalias1::Some.IPrintable.Print()=>this.aspect1.Print();}

Nested types

Manually written source:

namespaceScope{publicclassWrapper{publicinterfaceIPrintable{voidPrint();}}}publicpartialclassPerson:Scope.Wrapper.IPrintable{[BeaKona.AutoInterface]privatereadonlyScope.Wrapper.IPrintableaspect1=newPersonPrinterV1();}

Auto-generated accompanying source:

partialclassPerson{voidScope.Wrapper.IPrintable.Print()=>this.aspect1.Print();}

Verbatim names

Manually written source:

interfaceIPrintable{voidPrint();}publicpartialclassPerson:IPrintable{[BeaKona.AutoInterface]privatereadonlyIPrintable@object=newPersonPrinterV1();}

Auto-generated accompanying source:

partialclassPerson{voidIPrintable.Print()=>this.@object.Print();}