Skip to content

Commit

Permalink
more on Upgrade_20201110_DotNet5
Browse files Browse the repository at this point in the history
  • Loading branch information
olmobrutall committed Nov 12, 2020
1 parent cabb487 commit 227a8e7
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 36 deletions.
76 changes: 40 additions & 36 deletions Signum.Upgrade/CodeFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -122,18 +122,18 @@ public void RemoveAllLines(Expression<Predicate<string>> condition)
});
}

public void InsertAfterFirstLine(Expression<Predicate<string>> condition, string otherLines)
public void InsertAfterFirstLine(Expression<Predicate<string>> condition, string text)
{
ProcessLines(lines =>
{
var pos = lines.FindIndex(condition.Compile());
if(pos == -1)
{
Warning($"Unable to find line where {condition} the insert after {otherLines}");
Warning($"Unable to find line where {condition} the insert after {text}");
return false;
}
var indent = GetIndent(lines[pos]);
lines.InsertRange(pos + 1, otherLines.Lines().Select(a => indent + a.Replace("Southwind", this.Uctx.ApplicationName)));
lines.InsertRange(pos + 1, text.Lines().Select(a => indent + a.Replace("Southwind", this.Uctx.ApplicationName)));
return true;
});
}
Expand All @@ -145,91 +145,90 @@ string GetIndent(string v)

/// <param name="fromLine">Not included</param>
/// <param name="toLine">Not included</param>
public void ReplaceBetween(Expression<Predicate<string>> fromLine, Expression<Predicate<string>> toLine, string otherLines
)
public void ReplaceBetween(Expression<Predicate<string>> fromLine, Expression<Predicate<string>> toLine, string text)
{
ProcessLines(lines =>
{
var from = lines.FindIndex(fromLine.Compile());
if (from == -1)
{
Warning($"Unable to find a line where {fromLine} to insert after {otherLines}");
Warning($"Unable to find a line where {fromLine} to insert after {text}");
return false;
}
var to = lines.FindIndex(from + 1, toLine.Compile());
if(to == -1)
{
Warning($"Unable to find a line where {toLine} after line {to} to insert before {otherLines}");
Warning($"Unable to find a line where {toLine} after line {to} to insert before {text}");
return false;
}
var indent = GetIndent(lines[from]);
lines.RemoveRange(from + 1, to - from - 1);
lines.InsertRange(from + 1, otherLines.Lines().Select(a => indent + a.Replace("Southwind", this.Uctx.ApplicationName)));
lines.InsertRange(from + 1, text.Lines().Select(a => indent + a.Replace("Southwind", this.Uctx.ApplicationName)));
return true;
});
}

public void ReplaceLine(Expression<Predicate<string>> condition, string otherLines)
public void ReplaceLine(Expression<Predicate<string>> condition, string text)
{
ProcessLines(lines =>
{
var pos = lines.FindIndex(condition.Compile());
if (pos == -1)
{
Warning($"Unable to find a line where {condition} to replace it by {otherLines}");
Warning($"Unable to find a line where {condition} to replace it by {text}");
return false;
}
var indent = GetIndent(lines[pos]);
lines.RemoveRange(pos, 1);
lines.InsertRange(pos, otherLines.Lines().Select(a => indent + a.Replace("Southwind", this.Uctx.ApplicationName)));
lines.InsertRange(pos, text.Lines().Select(a => indent + a.Replace("Southwind", this.Uctx.ApplicationName)));
return true;
});
}

public void InsertBeforeFirstLine(Expression<Predicate<string>> condition, string otherLines)
public void InsertBeforeFirstLine(Expression<Predicate<string>> condition, string text)
{
ProcessLines(lines =>
{
var pos = lines.FindIndex(condition.Compile());
if (pos == -1)
{
Warning($"Unable to find a line where {condition} to insert before {otherLines}");
Warning($"Unable to find a line where {condition} to insert before {text}");
return false;
}
var indent = GetIndent(lines[pos]);
lines.InsertRange(pos, otherLines.Lines().Select(a => indent + a.Replace("Southwind", this.Uctx.ApplicationName)));
lines.InsertRange(pos, text.Lines().Select(a => indent + a.Replace("Southwind", this.Uctx.ApplicationName)));
return true;
});
}

public void InsertAfterLastLine(Expression<Predicate<string>> condition, string otherLines)
public void InsertAfterLastLine(Expression<Predicate<string>> condition, string text)
{
ProcessLines(lines =>
{
var pos = lines.FindLastIndex(condition.Compile());
if (pos == -1)
{
Warning($"Unable to find a line where {condition} to insert after {otherLines}");
Warning($"Unable to find a line where {condition} to insert after {text}");
return false;
}
var indent = GetIndent(lines[pos]);
lines.InsertRange(pos + 1, otherLines.Lines().Select(a => indent + a.Replace("Southwind", this.Uctx.ApplicationName)));
lines.InsertRange(pos + 1, text.Lines().Select(a => indent + a.Replace("Southwind", this.Uctx.ApplicationName)));
return true;
});
}

public void InsertBeforeLastLine(Expression<Predicate<string>> condition, string otherLines)
public void InsertBeforeLastLine(Expression<Predicate<string>> condition, string text)
{
ProcessLines(lines =>
{
var pos = lines.FindLastIndex(condition.Compile());
if (pos == -1)
{
Warning($"Unable to find a line where {condition} to insert before {otherLines}");
Warning($"Unable to find a line where {condition} to insert before {text}");
return false;
}
var indent = GetIndent(lines[pos]);
lines.InsertRange(pos, otherLines.Lines().Select(a => indent + a.Replace("Southwind", this.Uctx.ApplicationName)));
lines.InsertRange(pos, text.Lines().Select(a => indent + a.Replace("Southwind", this.Uctx.ApplicationName)));
return true;
});
}
Expand All @@ -253,7 +252,15 @@ private void AssertExtension(params string[] extension)
throw new InvalidOperationException("");
}

public bool UpdateNugetReference(string packageName, string version)
public void UpgradeNpmPackage(string packageName, string version)
{
AssertExtension(".json");

this.ReplaceLine(condition: a => a.Contains(@$"""{packageName}"""),
text: @$"""{packageName}"": ""{version}""");
}

public void UpdateNugetReference(string packageName, string version)
{
AssertExtension(".csproj");

Expand All @@ -265,17 +272,16 @@ public bool UpdateNugetReference(string packageName, string version)
if (elem == null)
{
Warning($"Unable to find reference to Nuget {packageName} to update it to {version}");
return false;
}
else
{
elem.Attribute("Version")!.Value = version;

elem.Attribute("Version")!.Value = version;

this.Content = doc.ToString(SaveOptions.DisableFormatting);

return true;
this.Content = doc.ToString(SaveOptions.DisableFormatting);
}
}

public bool RemoveNugetReference(string packageName)
public void RemoveNugetReference(string packageName)
{
AssertExtension(".csproj");

Expand All @@ -287,17 +293,16 @@ public bool RemoveNugetReference(string packageName)
if (eleme == null)
{
Warning($"Unable to remove reference to Nuget {packageName} because is not found");
return false;
}
else
{
eleme.Remove();

eleme.Remove();

this.Content = doc.ToString(SaveOptions.DisableFormatting);

return true;
this.Content = doc.ToString(SaveOptions.DisableFormatting);
}
}

public bool AddNugetReference(string packageName, string version)
public void AddNugetReference(string packageName, string version)
{
AssertExtension(".csproj");

Expand All @@ -312,7 +317,6 @@ public bool AddNugetReference(string packageName, string version)

this.Content = doc.ToString(SaveOptions.DisableFormatting);

return true;
}
}

Expand Down
23 changes: 23 additions & 0 deletions Signum.Upgrade/Upgrades/Upgrade_20201110_DotNet5.cs
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,29 @@ public override void Execute(UpgradeContext uctx)
"public bool Match(HttpContext? httpContext, IRouter? route, ");
});

uctx.ChangeCodeFile($@"Southwind.React/package.json", file =>
{
file.UpgradeNpmPackage("node-sass", "5.0.0");
file.UpgradeNpmPackage("sass-loader", "10.1.0");
});

uctx.ChangeCodeFile($@"Southwind.React/Dockerfile", file =>
{
file.ReplaceLine(
a=>a.Contains("FROM mcr.microsoft.com/dotnet/core/aspnet"),
"FROM mcr.microsoft.com/dotnet/aspnet:5.0-buster-slim AS base");
file.ReplaceLine(
a => a.Contains("FROM mcr.microsoft.com/dotnet/core/sdk"),
"FROM mcr.microsoft.com/dotnet/sdk:5.0-buster-slim AS build");

file.ReplaceBetween(
a => a.Contains("RUN apt-get -y install curl"),
a => a.Contains("RUN apt-get -y install nodejs"),
@"RUN apt-get -y install curl
RUN curl -sL https://deb.nodesource.com/setup_15.x | bash -
RUN apt-get install -y nodejs");
});

}
}
}

13 comments on commit 227a8e7

@olmobrutall
Copy link
Collaborator Author

@olmobrutall olmobrutall commented on 227a8e7 Nov 12, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Switch to .Net 5 and C# 9

If you have lived under a rock, .Net 5 was presented last Tuesday in Net Conf. Some links to know more about it:

This release also introduces C#9 with a lot of cool new stuff:

I haven't had time to play with the new language features yes, but I've been preparing for this update since the last preview, so the master branch now depends on .Net 5, while masterCore3 will stay in the last version compatible with .Net Core 3.1

Another wave of nullability warnings

The main changes where updating the code to the next wave of errors because of the new nullability annotations in .Net 5.0. Specially annoying was dealing with LINQ to XML constructors.

Switch to System.Text.Json

Another big thing is that in .Net 5 the BinaryFormatter has been removed. Signum.React uses Json for most of the serialization, except for the Authentication Token (that contains the User serialized and encrypted to avoid database queries on every request) that used BinaryFormatter.

The solution was to generalize the Signum.React Json infrastructure to serialize and deserialize entities (EntityJsonConverter, MListJsonConverter, LiteJsonConverter, ...) to be able to work without a database and outside of a Web.API pipline.

Also, now that I was on it, I migrated the converters from Newtonsoft.Json to System.Text.Json. This new library is based in Span<T> so it has great performance. It was available since .Net Core 3.1 but was missing some important features preventing the migration.

All in all, now the serialization infrastructure is in Signum.Engine, uses System.Text.Json and can also be used to serialize arbitrary entities in a .json file.

How to update

Finally, I have a a big surprise to improve the developer experience when updating the framework: Signum.Upgrade

@rezanos
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Hooray!
Excellent! 👏 👏

@fmelendezherize
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Congratz!!

@olmobrutall
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rezanos thanks :)
@fmelendezherize great to see new faces, are you using Signum Framework from Venezuela?

@JesusFrancesGarcia
Copy link
Contributor

@JesusFrancesGarcia JesusFrancesGarcia commented on 227a8e7 Nov 13, 2020 via email

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@MehdyKarimpour
Copy link
Contributor

@MehdyKarimpour MehdyKarimpour commented on 227a8e7 Nov 13, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Congratulation, Awesome job!

@MehdyKarimpour
Copy link
Contributor

@MehdyKarimpour MehdyKarimpour commented on 227a8e7 Nov 13, 2020 via email

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@fmelendezherize
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rezanos thanks :)
@fmelendezherize great to see new faces, are you using Signum Framework from Venezuela?

Te respondo en español Olmo, estoy usando Signum en mi aplicacion administrativa probablemente desde que la crearon hace cuanto ya? 10 años, tal vez un poco menos. El punto es que he estado usando una version antigua de la libreria y solo la parte de Data (Entities - Engine). Ahora que NET 5 fue liberada, hago un repaso y estoy tratando de estar mas activo, con lo que han trabajado durante todos estos años. Si, estamos operando desde Venezuela, estamos a la orden. Saludos

@olmobrutall
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Increible :) siempre hace ilusión conocer gente que lo usa! Y desde hace tanto tiempo!

En que UI estáis? Windows, Web o React? Y de que fecha es la version del Framework?

@fmelendezherize
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Es una aplicacion administrativa para Desktop WPF. Comenzo en aquellos entonces con .net framework 2.0? si mal no recuerdo. He tratado de actualizarlo a las versiones de framework mayores como la 3.5 y la 4.6 pero ahorita que salto a Core, pues espere un poco. Con Net 5 no hay forma de no migrar hacia alla porque todo el ecosistema lo hara.
Signum

Hasta la tercera version del sistema usamos esa version de Signum.Entities del 2011 y ahora usamos una version del 2016. Te iba a preguntar que politica usaron para la version de las librerias porque noto que la nueva dice 1.0

@olmobrutall
Copy link
Collaborator Author

@olmobrutall olmobrutall commented on 227a8e7 Nov 13, 2020

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Signum Framework se distribuye como código fuente, no como librería. Eso hace que tenga muy poca fricción hacer mejoras en el Framework directamente mientras cambias la aplicación y permite que haya una evolución constante del framework especialmente para cosas pequenyas.

Calculo que al menos el 50% de los cambios del framework son ese tipo de mejoras incrementales hechas por mí o por otros colaboradores, mientras que el otro 50% son grandes avances técnicos o nuevas funcionalidades que a menudo suelo hacer en mi tiempo libre. .

En la practica eso significa que prácticamente siempre estés en una versión 'no oficial' y al no haber una publicación (Codigo -> DLL), dar un número de versión es muy artificial.

La versión es el commit del submodulo. Estás usando Git y Git-submodulos? no recuerdo exactamente cuando empezamos a usarlo pero sería alrededor de 2011 o 2012.

Una vez acabado Signum.React eliminamos Signum.Web para evitar duplicidades, y al portar a .Net Core 2.0 eliminamos Signum.Windows porque realmente había pocos (ningún?) cliente que los estaba usando y llevaba tiempo un poco abandonado.

Desde .Net Core 3.0 hay soporte para WinForms y WPF, así que técnicamente podría devolverse a la vida y hacer una migración más sencilla para ti y algún otro proyecto que aún usa Signum.Windows, pero posiblemente volvería a quedar en un cierto estado de abandono si no hay clientes que pidan aplicaciones para Windows.

Como de posible ves una migración a Signum.React? Tienes tú o tu equipo ciertos conocimientos de web ? (Javascript, Typescript, React, etc...)

@fmelendezherize
Copy link

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Signum Framework se distribuye como código fuente, no como librería. Eso hace que tenga muy poca fricción hacer mejoras en el Framework directamente mientras cambias la aplicación y permite que haya una evolución constante del framework especialmente para cosas pequenyas.

Calculo que al menos el 50% de los cambios del framework son ese tipo de mejoras incrementales hechas por mí o por otros colaboradores, mientras que el otro 50% son grandes avances técnicos o nuevas funcionalidades que a menudo suelo hacer en mi tiempo libre. .

En la practica eso significa que prácticamente siempre estés en una versión 'no oficial' y al no haber una publicación (Codigo -> DLL), dar un número de versión es muy artificial.

La versión es el commit del submodulo. Estás usando Git y Git-submodulos? no recuerdo exactamente cuando empezamos a usarlo pero sería alrededor de 2011 o 2012.

Una vez acabado Signum.React eliminamos Signum.Web para evitar duplicidades, y al portar a .Net Core 2.0 eliminamos Signum.Windows porque realmente había pocos (ningún?) cliente que los estaba usando y llevaba tiempo un poco abandonado.

Desde .Net Core 3.0 hay soporte para WinForms y WPF, así que técnicamente podría devolverse a la vida y hacer una migración más sencilla para ti y algún otro proyecto que aún usa Signum.Windows, pero posiblemente volvería a quedar en un cierto estado de abandono si no hay clientes que pidan aplicaciones para Windows.

Como de posible ves una migración a Signum.React? Tienes tú o tu equipo ciertos conocimientos de web ? (Javascript, Typescript, React, etc...)

Hola Olmo, bueno precisamente ese es el punto que estabamos usando Signum, en la era pre-github y pues no habia iniciado trabajo de migracion porque me habia sido muy estable, y recuerda que la tenia limitada solo a la parte de repositorios y data. Se que han hecho un gran esfuerzo añadiendo muchas otras utilidades y precisamente planeo ponerme al dia con Signum.

Por lo pronto te respondo que la aplicacion se va a mantener Desktop - WPF no tenemos pensado hacer migracion a app web. Pero si tengo en mente crear aplicaciones nueva que depende de mis librerias principales por eso ando considerando mas bien hacerlo en Blazor que esta cada vez mas maduro (que opinion tienes al respecto?).

Lo que si quiero hacer ademas es migrar al menos todas mis librerias base de mi aplicacion adiministrativa a la ultima version de Signum en NET 5, que consejo me pudieras dar para migrar de .net framework 4.* a NET 5? (mis librerias, Signum ya lo compile a NET 5 sin problemas).

Saludos

@olmobrutall
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Han habido muchos cambios desde .Net Framework 4.7 pero la mayoría en React o cambios internos. Que recuerde los cambios más importantes en Entities y Engine son nullable reference types y AutoExpressionField. Pides ver más detalles en el changelog https://github.com/signumsoftware/framework#changelog

Por otro lado .Net core tiene 2-3 años de antigüedad, pero tu tienes una aplicación bastante más antigua. No se en que estado estará el código, por ejemplo a nivel de convenciones (DN->Entity,Embedded,Model o Mixin) attributos como EntityKind o PropertyValidation con nameof.

Finalmente, piensa que usar Signum Framework como un ORM tiene sentido para aplicación o módulos que van a ser usados por el público en general, pero para una aplicación de negocio interna, te estás perdiendo MUCHO si no usas la interfaz de usuario o los módulos de Extensions.

Igual antes de hacer la migración merece la pena bajarte southwind o clonarte una aplicación nueva para ver las capacidades del buscador, charting, autorización, etc... y decidir luego si la mejor estrategia es evolución o revolución

Please sign in to comment.