[ADCES]Programmer2Head & DataPreparation with JupyterNotebooks
Prezentare 1:
Titlu: De la “just a programmer” la “head of his software company”
Descriere : Despre o calatorie care a inceput, nu intr-un garaj american, ci la Automatica, si care a continuat pe 3 continente
Prezentator: Radu Iovescu , https://www.linkedin.com/in/riovescu/
Prezentare 2:
Titlu: Data Preparation with Jupyter Notebook and DataFrame
Descriere::
Prezentator: Daniel Costea, MVP, https://mvp.microsoft.com/en-us/PublicProfile/5003534
Va astept miine, 9 februarie , la https://www.meetup.com/Bucharest-A-D-C-E-S-Meetup/events/275609419/
Friday Links 409
AOPMethods–dogfooding
I was trying to apply AOPMethods to – surprise! – AOPMethods project itself. And I have discovered a new reason: I do not want to make the methods public. I just want to put try/catch around them to know what is wrong.
The fast – and not so good – idea was to transform
MethodPrefix =”pub”
into a
Dictionary<MethodsPrefix: string, VIsibilty: string>
in order to pass something like that
{ “pub”, “public” } , {“prv”, “private”}
The second idea was better : what if I allow multiple instances and generate accordingly ?
So I came up with this definition
[AutoMethods(template = TemplateMethod.MethodWithPartial, MethodPrefix =”pub”)]
[AutoMethods(template = TemplateMethod.CustomTemplateFile,CustomTemplateFileName =”privateTryCatch.txt”, MethodSuffix = “bup”)]
partial class Person
And the code processes both attributes – and generates the code. One slightly problem: Cannot have GeneratedCode and CompilerGenerated on both generated files. But – it works!
Friday Links 408
AOPMethods–adding partial functions and enums
I was finishing the AOPMethods – and what I have been thinking is – why not add partial functions ? I have added Console.Write, but … this seems more general… So , now , this is the Person class definition with the partial function definition
[AutoMethods(template = TemplateMethod.MethodWithPartial, MethodPrefix =”pub”, MethodSuffix =”bup”)]
partial class Person
{
partial void Method_Start(string methodName)
{
Console.WriteLine($”start {methodName}”);
}
partial void Method_End(string methodName)
{
Console.WriteLine($”end {methodName}”);
}
And, because I have finished the AOPMethods , I have been thinking about the problems with enums – every time I parse the enum. What about a autogenerated function ? So now , with this definition:
[AutoEnum(template = EnumMethod.GenerateExtensionCode)]
/// <summary>
/// my test
/// </summary>
public enum Test:long
{
a,
//the b should be 1
b,
/// <summary>
/// x should be 2
/// </summary>
x=5,
y=7}
I can do this
long y = 7;
var s = y.ParseExactTest2();
var q=y.ToString().ParseExactTest2();
var s1 = s.ToString().ParseExactTest2();
For reference, the generated code with Roslyn AOPMethods is:
public static AOPMethodsTest.Test2 ParseExactTest2(this long value, AOPMethodsTest.Test2? defaultValue = null)
{
if (0 == value)
return AOPMethodsTest.Test2.a1;
if (1 == value)
return AOPMethodsTest.Test2.b1;
if (5 == value)
return AOPMethodsTest.Test2.x1;
if (7 == value)
return AOPMethodsTest.Test2.y1;if (defaultValue != null)
return defaultValue.Value;throw new ArgumentException(“cannot find ” + value + ” for AOPMethodsTest.Test2 “);
}public static AOPMethodsTest.Test2 ParseExactTest2(this string value, AOPMethodsTest.Test2? defaultValue = null)
{
//trying to see if it is a value inside
//if(!string.IsNullOrWhiteSpace)
if (long.TryParse(value, out long valueParsed))
{
return ParseExactTest2(valueParsed);
}if (0 == string.Compare(“a1”, value, StringComparison.InvariantCultureIgnoreCase))
return AOPMethodsTest.Test2.a1;
if (0 == string.Compare(“b1”, value, StringComparison.InvariantCultureIgnoreCase))
return AOPMethodsTest.Test2.b1;
if (0 == string.Compare(“x1”, value, StringComparison.InvariantCultureIgnoreCase))
return AOPMethodsTest.Test2.x1;
if (0 == string.Compare(“y1”, value, StringComparison.InvariantCultureIgnoreCase))
return AOPMethodsTest.Test2.y1;if (defaultValue != null)
return defaultValue.Value;throw new ArgumentException(“cannot find ” + value + ” for AOPMethodsTest.Test2 “);
}
AOP Methods–Problems in running and solving
The problems that I have encountered were:
1. The ThisAssembly RoslynGenerator that I use should not be put as reference in the nuget. I have fixed this by adding
<PackageReference Include=”ThisAssembly.AssemblyInfo” Version=”1.0.0″ ReferenceOutputAssembly=”false” />
2. I have problems generating code to async code with Task . The problem was that I have added logging ( very basic – Console.WriteLine) and the order of the logging was errating. I figured out that I should must use the async /await and then my template was modified as
strAwait = “”
strAsync =””
if mi.IsAsync == true
strAwait = ” await “
strAsync = ” async “
endpublic {{strAsync}} {{mi.ReturnType}} {{mi.NewName}} ({{mi.parametersDefinitionCSharp }} {{separator}}
//more code
{{
if mi.ReturnsVoid == false
}}
return
{{
end
}}
{{ strAwait }}{{mi.Name}}({{ mi.parametersCallCSharp }});
And this is worth noting.
AOP Methods–Code
The code is not so much different from SkinnyControllers : Implement ISourceGenerator , putting the Generator attribute on the class
[Generator]
public partial class AutoActionsGenerator : ISourceGenerator
inspecting the classes if they have the common attribute , generating code with Scriban
The problem was : How can the AOPMethods can
- differentiate between the private function that must be made public
- generate the code for a similar public function, with same parameters (and maybe more) , but with different name ?
So I decide to go the route of convention: The programmer will declare the private function that he wants to autmatically make public ( and add templating code ) with a prefix or a suffix . This will be declared into the attribute of the class – and that will be all.
For example , I have this method
public string FullName()
{
return FirstName + ” ” + LastName;
}
That I want to monitor ( add logs, info and so on ) . I will make it private and start with pub
private string pubFullName()
{
return FirstName + ” ” + LastName;
}
Then , on the class , I will declare the pub prefix
[AutoMethods(template = TemplateMethod.CallerAtttributes, MethodPrefix =”pub”, MethodSuffix =”bup”)]
And the following will be generated
public string FullName(
[CallerMemberName] string memberName = “”,
[CallerFilePath] string sourceFilePath = “”,
[CallerLineNumber] int sourceLineNumber = 0)
{
try
{
Console.WriteLine(“–pubFullName start “);
Console.WriteLine(“called class :” + memberName);
Console.WriteLine(“called file :” + sourceFilePath);
Console.WriteLine(“called line :” + sourceLineNumber);return
pubFullName();
}
catch (Exception ex)
{
Console.WriteLine(“error in pubFullName:” + ex.Message);
throw;
}
finally
{
Console.WriteLine(“——–pubFullName end”);
}}
The caller attributes templates can be found at AOP_With_Roslyn\AOPMethods\AOPMethods\templates\CallerAtttributes.txt
//——————————————————————————
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
// </auto-generated>
//——————————————————————————
using System;
using System.CodeDom.Compiler;
using System.Runtime.CompilerServices;namespace {{NamespaceName}} {
/// <summary>
/// Generates code from {{ClassName}}
/// </summary>
[GeneratedCode(“AOPMethods”, “{{version}}”)]
[CompilerGenerated]
partial class {{ClassName}}{
/*
public int id(){
System.Diagnostics.Debugger.Break();
return 1;
}
*/
{{~ for mi in Methods ~}}
{{
separator = “”
if(mi.NrParameters > 0)
separator = “,”
end
strAwait = “”
strAsync =””
if mi.IsAsync == true
strAwait = ” await “
strAsync = ” async “
end
}}
public {{strAsync}} {{mi.ReturnType}} {{mi.NewName}} ({{mi.parametersDefinitionCSharp }} {{separator}}
[CallerMemberName] string memberName = “”,
[CallerFilePath] string sourceFilePath = “”,
[CallerLineNumber] int sourceLineNumber = 0){
try{
Console.WriteLine(“–{{mi.Name}} start “);
Console.WriteLine(“called class :”+memberName );
Console.WriteLine(“called file :”+sourceFilePath );
Console.WriteLine(“called line :”+sourceLineNumber );
{{
if mi.ReturnsVoid == false
}}
return
{{
end
}}
{{ strAwait }}{{mi.Name}}({{ mi.parametersCallCSharp }});
}
catch(Exception ex){
Console.WriteLine(“error in {{mi.Name}}:” + ex.Message);
throw;
}
finally{
Console.WriteLine(“——–{{mi.Name}} end”);
}}
{{~ end ~}}
}
}
You can add logging , security, anything else that is a vertical to the business
AOP Methods–Introduction
As I have done with Roslyn for SkinnyControllers , I said – what about generating public methods at compile time ?
For example, what if this method
private string pubFullName()
{return FirstName + ” ” + LastName;
}
is transformed into this
public string FullName(
[CallerMemberName] string memberName = “”,
[CallerFilePath] string sourceFilePath = “”,
[CallerLineNumber] int sourceLineNumber = 0)
{
try
{
Console.WriteLine(“–pubFullName start ” + _cc);
Console.WriteLine(“called class :” + memberName);
Console.WriteLine(“called file :” + sourceFilePath);
Console.WriteLine(“called line :” + sourceLineNumber);return pubFullName();
}
catch (Exception ex)
{
Console.WriteLine(“error in pubFullName:” + ex.Message);
throw;
}
finally
{
Console.WriteLine(“——–pubFullName end”);}
}
automatically, based on a template ? And all methods will have this ?
Enter AOP Methods : https://www.nuget.org/packages/AOPMethodsGenerator/ and https://www.nuget.org/packages/AOPMethodsCommon/
The first one is the generator. The second one is containing the attribute that tells to transform.