<![CDATA[mymemoryleaks]]>http://www.mymemoryleaks.fr/http://www.mymemoryleaks.fr/favicon.pngmymemoryleakshttp://www.mymemoryleaks.fr/Ghost 1.21Fri, 20 Apr 2018 12:40:41 GMT60<![CDATA[Blazor : Injectez vos interop Javascript]]>

Commençons par ce qui fait mal. Je dois avouer que ce blog post fait suite à un fail.
Dans cette version 0.2 de Blazor, il y a pas mal de code glue à produire pour pouvoir appeler une fonction javascript à partir de votre code C#.

Cela se passe

]]>
http://www.mymemoryleaks.fr/blazor-injectez-vos-interop-js/5ad8f208dfa53d0bcc07902fFri, 20 Apr 2018 12:40:03 GMTBlazor : Injectez vos interop Javascript

Commençons par ce qui fait mal. Je dois avouer que ce blog post fait suite à un fail.
Dans cette version 0.2 de Blazor, il y a pas mal de code glue à produire pour pouvoir appeler une fonction javascript à partir de votre code C#.

Cela se passe en 2 étapes :

  • A partir de votre code javascript, il faut enregistrer une fonction dans le contexte de Blazor.
Blazor.registerFunction('DisplayAlert', (data) => {
        alert(data);
        return true;
});
  • Quand vous souhaitez faire appel à cette fonction on utilisera alors un code de ce type, cette fois ci dans votre code C#.
RegisteredFunction.Invoke<bool>("DisplayAlert", text);

On remarque que tout ca fonctionne à base de magic strings (le nom de la methode), que les functions sont obligées de retourner une valeur (void n'est pas prit en compte pour l'instant), et puis ce RegisteredFunction.Invoke c'est vraiment pas super sexy.

Du coup je m'étais dis, ca pourrait être sympa d'au moins cacher RegisteredFunction.Invoke, et voici comment j'imaginais la chose.

On pourrait commencer par définir l'ensemble des fonctions js dans une interface C#, un peu comme ca :

public interface IAlerter
{
    bool DisplayAlert(string text);
}

Le choix de l'interface n'est pas complétement anodin, Retyped propose un grand nombre de librairies js exposées sous forme d'interface C#, ce qui nous ouvre la porte a plein de possibilités.

Pour en revenir à notre interface IAlerter, on peut l'injectée dans notre component Blazor à l'aide de l'attribut ***[Inject]***, comme ceci.

public class Interoper : BlazorComponent
{
    [Inject]
    protected IAlerter Alerter { get; set; }

    public string Sometext { get; set; }

    public virtual void Say()
    {
        Alerter.DisplayAlert(Sometext);
    }
}

Et finalement il nous ne nous manque qu'un petit helper magique produisant une implémentation de l'interface IAlerter se chargeant de faire les RegisteredFunction.Invoke qui vont bien. Un truc qui pourrait ressembler à ca :

var alerter = Substitute.For<IAlerter>();
alerter.DisplayAlert(Arg.Any<string>())
       .Returns(info => RegisteredFunction.Invoke<bool>("DisplayAlert", info.ArgAt<string>(0)));

Evidemment ici, je vous présente la version naïve qui ne fonctionne que pour notre interface, mais avec un peu de reflection on peut rendre cela générique sans trop de mal.

Le fail est sous vos yeux, si vous executez ça dans la console de votre navigateur vous aller voir une très belle exception avec un stack de 3 pieds de long. (@Charly, elle est pour toi celle-ci)

Blazor : Injectez vos interop Javascript

Une grosse PlatformNotSupportedException! Impossible d' utiliser l'api System.Reflection.Emit avec Mono Webassembly. C'est emmerdant, mais en y reflechissant bien, c'est pas déconnant si on veut maintenir un framework pas trop fat dans le navigateur.

L'expérimentation sur ce point précis s'arrete donc la, mais tout n'est pas à jeter.
Je retiens de cette aventure l'organisation du code. Une interface décrivant l'interop javascript, qui sera injectée dans les BlazorComponent, et une implémentation concrète de l'interface, comme ceci.

public class Alerter : IAlerter
{
    public bool DisplayAlert(string text)
    {
        return RegisteredFunction.Invoke<bool>("say", text);
    }
}

On est pas allé aussi loin que je ne l'aurais espéré, mais qui sait dans une prochaine version de Blazor cela sera peut etre possible.

]]>
<![CDATA[Astuce Blazor : Séparer la vue du code]]>

Depuis quelque temps dans la communauté .NET on parle fait pas mal de marketing autour de Blazor. Je ne vais pas vous présenter cette nouvelle techno... si vous etes ici, c'est que vous connaissez déjà :).

Une des premières choses qui m'a embété fut de voir dans les articles de présentation

]]>
http://www.mymemoryleaks.fr/astuce-blazor/5ace6f9b90a63023940f731fWed, 11 Apr 2018 21:17:03 GMTAstuce Blazor : Séparer la vue du code

Depuis quelque temps dans la communauté .NET on parle fait pas mal de marketing autour de Blazor. Je ne vais pas vous présenter cette nouvelle techno... si vous etes ici, c'est que vous connaissez déjà :).

Une des premières choses qui m'a embété fut de voir dans les articles de présentation un mélange sans vergogne du code html et du code .NET wrappé dans la section @functions

je parle de ca :

@using System
@page "/guid"


    <h1>Guid Generator</h1>

    <input type="text" value="@generatedGuid"/><button type="button" @onclick(Generate)>Generate!</button>

    @functions {

        string generatedGuid = string.Empty;

        private void Generate()
        {
            generatedGuid = Guid.NewGuid().ToString();
        }
    }

Evidemment, ici le code est extremement simple, mais dans la vraie vie j'vous le donne dans le mille on aurait envie de faire des tests unitaires de notre code C#.

Je vous propose donc cette facon de faire. On va créer un classe qui hérite de BlazorComponent et on y mettra notre code métier.

Commençons par créér une classe qui contiendra notre code behind

using System;
using Microsoft.AspNetCore.Blazor.Components;

namespace OwnBlazor.Pages
{
    public class GuidGenerator : BlazorComponent
    {
        public string GeneratedGuid { get; set; }

        public void Generate()
        {
            GeneratedGuid = Guid.NewGuid().ToString();
        }
    }
}

la seule chose qu'il faut noter ici, c'est que notre classe hérite de BlazorComponent

Passons à notre vue qui est maintenant beaucoup plus propre.

@page "/guid2"
@inherits OwnBlazor.Pages.GuidGenerator

    <h1>Guid Generator</h1>

    <input type="text" value="@GeneratedGuid"/><button type="button" @onclick(Generate)>Generate</button>

Dans la vue on spécifiera que l'on hérite de notre classe GuidGenerator précédement créée.

Voila, c'est quand même un peu plus propre et surtout pn peut facilement tester notre code C#.

]]>
<![CDATA[Combiner des Expressions Trees]]>

Il y a tout juste quelques jours, on pair programmait avec Anthony sur un projet. Nous nous sommes retrouvés a vouloir combiner au runtime des Expressions trees en fonction de parametres évalués au runtime.

En gros on avait envie d'écrire un truc du genre

Expression<Func<Person, bool&
]]>
http://www.mymemoryleaks.fr/combiner-des-expressions-trees/5ac3d3fab8151d4864f88e10Tue, 03 Apr 2018 21:43:43 GMTCombiner des Expressions Trees

Il y a tout juste quelques jours, on pair programmait avec Anthony sur un projet. Nous nous sommes retrouvés a vouloir combiner au runtime des Expressions trees en fonction de parametres évalués au runtime.

En gros on avait envie d'écrire un truc du genre

Expression<Func<Person, bool>> predicate = x => x.Id > 1;

puis un peu plus loin

predicate += x => x.Name.Length < 6;

Ne cherchez pas à compiler ca, le compilo risque de se rebeller.

On était un peu pris par le temps, du coup on a fait un simple. Néanmoins je profite de cet espace pour partager avec vous une facon de faire pour combiner des Expressions et faire du code un peu plus sexy

Pour faire plaisir à maitre Etienne on va travailler a base de tests unitaires.

Commençons par la version naïve; En cherchant un peu sur la msdn on tombera facilement sur Expression.AndAlso permettant de créer une nouvelle expression qui combine deux Expressions left et right

        [Fact]
        public void SimpleCombining_Fails()
        {
            // Arrange
            Expression<Func<Person, bool>> firstPredicate = x => x.Id > 1;
            Expression<Func<Person, bool>> secondPredicate = x => x.Name.Length < 6;
            
            Expression binaryexp = Expression.AndAlso(firstPredicate.Body, secondPredicate.Body);
            ParameterExpression[] parameters = {
                Expression.Parameter(typeof(Person), firstPredicate.Parameters.First().Name)
            };
            
            Expression<Func<Person, bool>> lambda = Expression.Lambda<Func<Person, bool>>(binaryexp, parameters);
            
            // Act
            Action filter = () => {
                var combinedPredicate = lambda.Compile();
                var result = _persons.Where(combinedPredicate);
            };

            // Assert
            Assert.Throws<InvalidOperationException>(() => filter());
        }

On commence par définir nos deux prédicats (left & right) que l'on combine dans une expression binaire AndAlso (et logique) en utilisant comme paramètre générique T le paramètre utilisé dans la premiere expression initiale.
On essaye par la suite d'utiliser la lambda créée pour l'occasion dans une instruction Where que vous connaissez tous en Linq.

Bon, j'avais déjà vendu la méche en disant que c'était une version naïve; effectivement a l'execution vous allez avoir une InvalidOperationException

System.InvalidOperationException: 'variable 'x' of type 'AndOrExpressions.Person' referenced from scope '', but it is not defined'

Pour faire simple, dans nos deux expressions initiales, le paramètre x bien qu'il se nomme de la même maniere et soit du même type, il ne s'agit pas du meme objet. x est donc inconnu dans la seconde expression.

Etant donné que les Expressions sont des objets immutables il va nous falloir un moyen de créer/réécrire une expression donnée.

C'est pour ce genre de cas qu'MS a mis à notre disposition la classe ExpressionVisitor. Celle-ci nous permet de traverser l'expression tree et d'apporter des modifications. Rappelez vous que chaque modification produira une nouvelle expression, c'est le principe même de l'immutabilité.

Ok, commencons par créer une visiteur qui remplacera un paramètre T par un autre passé en paramètre.

public class ReplaceExpressionVisitor : ExpressionVisitor
    {
        private readonly Expression _searched;
        private readonly Expression _replacement;

        public ReplaceExpressionVisitor(Expression searched, Expression replacement)
        {
            _searched = searched;
            _replacement = replacement;
        }

        public override Expression Visit(Expression node)
        {
            if (node == _searched)
            {
                return _replacement;
            }   
            return base.Visit(node);
        }
    }

Simple, non?

Du coup si on réécrivait notre test de la facon suivante en imaginant une methode And qui permet de combiner des Expressions

[Fact]
        public void ReplacingType_Succeed()
        {
            // Arrange
            Expression<Func<Person, bool>> firstPredicate = x => x.Id > 1;
            Expression<Func<Person, bool>> secondPredicate = x => x.Name.Length < 6;

            Func<Person, bool> combinedPredicate = firstPredicate.And(secondPredicate);
            
            // Act
            var result = _persons.Where(combinedPredicate);

            // Assert
            Assert.Collection(result, people => Assert.Equal(people, Anto));
        }

Il ne nous reste qu'à définir une methode d'extension qui répond a cette signature, comme ceci :

public static class ExpressionsExtensions
    {
        public static Func<T, bool> And<T>(this Expression<Func<T, bool>> firstOperand, Expression<Func<T, bool>> secondOperand)
        {
            var replacement = Expression.Parameter(typeof(T));

            var leftVisitor = new ReplaceExpressionVisitor(firstOperand.Parameters[0], replacement);
            var left = leftVisitor.Visit(firstOperand.Body);

            var rightVisitor = new ReplaceExpressionVisitor(secondOperand.Parameters[0], replacement);
            var right = rightVisitor.Visit(secondOperand.Body);

            return Expression.Lambda<Func<T, bool>>(Expression.AndAlso(left, right), replacement)
                             .Compile();
        }
    }

Cette methode va combiner avec Expression.AndAlso nos deux expressions initiales, mais cette fois ci on aura prit soin de les réécrire en utilisant le même paramètre générique. Et évidemment cette fois-ci, le test est vert :)

]]>
<![CDATA[J'recommence, je git mon blog!]]>http://www.mymemoryleaks.fr/on-recommence-je-git-mon-blog/5ac27ad4a9a75b30c4d00a70Mon, 02 Apr 2018 20:20:21 GMTJ'recommence, je git mon blog!

J'ai passé 8 ans la-bas, sur blogger. Si je me souviens bien c'est Francois qui m'avais recommandé cette plateforme. Puis le temps à passé, François comme beaucoup d'autres ont bougé vers d'autres horizons, wordpress par exemple.

Pas moi... un peu par flemme, faut bien le dire.

Parfois l'idée et l'envie de pondre un article est la, mais compliqué de le faire dans le train car faut etre connecté sur blogger.com pour pouvoir écrire. D'autres problématiques se font sentir, ou stocker les images/screenshots etc...

Bref, il etait temps de demenager. Mais pour aller ou?

J'en ai parlé à mes collègues chez mon client actuel. J'voulais un truc light, facile à heberger, avec lequel je pouvais travailler en mode déconnecté. On a parlé de Ghost, de Jekyll, et puis des modes d'hébergement. Et la ca a fait tilt quand Anthony m'a rappelé qu'il y avait les github pages. En deux mots, un repository git qui est exposé comme un site web.
Merci encore pour le brainstorming mon grand!

D'ailleurs dans un prochain billet, je détaillerai la solution technique derrière ce blog, et comment j'ai rapatrié tous les posts depuis mon ancienne plateforme.
Ho, j'oubliais, github pages est si smart que j'ai même pu investir dans un nom de domaine (deux en réalité) et l'affecter à ce repository git.

Me revoilà donc, sous une nouvelle forme visuelle mais comme avant, pour partager mes pérégrinations autours des technos Microsoft.

]]>
<![CDATA[Déployer un webjob avec VSTS]]>

Si vous avez déjà eu besoin de déployer un azure webjob via vsts, vous avez du tomber sur ce bon blog post de Thomas Hellstrøm. Néanmoins, en suivant telles quelles les instructions de notre ami Thomas, vous risquer de casser la webapp qui host votre webjob.

Ce blog post va

]]>
http://www.mymemoryleaks.fr/deployer-un-webjob-avec-vsts/5a99b626f336bf15fc91af81Fri, 09 Feb 2018 22:52:00 GMT

Si vous avez déjà eu besoin de déployer un azure webjob via vsts, vous avez du tomber sur ce bon blog post de Thomas Hellstrøm. Néanmoins, en suivant telles quelles les instructions de notre ami Thomas, vous risquer de casser la webapp qui host votre webjob.

Ce blog post va prendre la tournure d’une recette de cuisine, d’un pense bête ; cela m’évitera de me reposer la même question dans quelques mois, et j'espère secrètement que cela puisse aider certains d'entre vous.

On commence donc par utiliser la fonction « Publish as Azure Webjob » à partir de Visual Studio 2017.

Pas la peine d’aller au bout du deploy, ce tool va ajouter le package nuget Microsoft.Web.WebJobs.Publish et créer le fichier « webjob-publish-settinps.json » dans le répertoire properties de votre projet.

On passe ensuite sur le build sur VSTS. Thomas nous propose de définir les arguments suivants sur la tache msbuild :

/p:DeployOnBuild=true /p:WebPublishMethod=Package /p:PackageAsSingleFile=true /p:SkipInvalidConfigurations=true /p:Configuration=Release

Notez le paramètre « /p:WebPublishMethod=Package », qui produira un fichier zip.

Et en jetant un œil dans le fichier zip, mauvaise surprise, on est en train de packager le dossier bin avec des dll qui vont venir écraser celles qui appartiennent à la webapp.

Du coup j’vous propose de corriger ça.
On commence par changer les arguments de la tache msbuild.

/p:DeployOnBuild=true /p:WebPublishMethod=FileSystem /p:publishUrl="$(build.artifactstagingdirectory)" /p:DeployDefaultTarget=WebPublish

Ce qui va produire le même contenu que le fichier zip mais directement sur le système de fichier.

Puis on ajoute une tache delete file, qui se chargera de supprimer le dossier /bin que nous voulons éviter de déployer.

Voila, cette fois ci nous y sommes. J’espère que cela pourra vous aider!

]]>
<![CDATA[VSTS – Quand y’a plus de crédits, y’en a encore.]]>

Ça, c’est la poisse: Your account has no free minutes remaining.

Le scénario est à se pendre, tu montes ton projet en intégration continue et après quelques (dizaines) de commit tu te retrouves dans l’impossibilité de complétera une PR ou juste vérifier que le dernier commit n’a

]]>
http://www.mymemoryleaks.fr/vsts-quand-ya-plus-de-credits-yen-a-encore/5a99b626f336bf15fc91af80Mon, 29 Jan 2018 23:14:00 GMT

Ça, c’est la poisse: Your account has no free minutes remaining.

Le scénario est à se pendre, tu montes ton projet en intégration continue et après quelques (dizaines) de commit tu te retrouves dans l’impossibilité de complétera une PR ou juste vérifier que le dernier commit n’a pas introduit de régressions.

Du coup je me propose de présenter ici, comment créer à moindre frais un agent de build sur-vitaminé. Et le fait d’avoir une machine un peu costaud, n’est pas un moindre mal ; qui ne s’est pas arraché les cheveux en attendant que l’agent de build hosté veuille bien se lancer et faire son travail… ?

Plutôt que de créer nous même une vm, installer windows, msbuild et tout le nécessaire a un agent de build, on va plutôt utiliser azure DevTest Lab. L’idée est de tirer parti des template de vm qui sont mises a notre dispo.

Après avoir créé votre première instance DevTest lab, on ajoute une vm basée sur l’image Visual Studio Community 2017 (latest release) on Windows Server 2016 (x64).

On va vous demander un login et un mot de passe pour le compte admin de la future vm.
Je vous conseille de stocker votre mot de passe dans le coffre-fort « my secret » pour une plus grande sécurité. (ce n’est donc pas mon mot de passe que vous voyez 😊)

Bon il nous faut maintenant choisir les caractéristiques de la vm. J’ai opté pour 32 GO de ram et 8 vcpu, une D8S_V3, elle ne sera allumée que quelques minutes le temps de faire le build, donc elle ne nous coutera pas bien cher.

Place aux artefacts, il convient de voir cela comme des scripts additionnels qui installeront d’autres programmes/services sur votre vm. Ça tombe bien, l’artefact VSTS Build agent nous procure le service de build qui convient.

Quelques précisions, le champs VSTS account name doit se conformer au pattern suivant : https://{{vsts_account_name}}.visualstudio.com

Le secret correspond une clé privée que vous pourrez crée en vous rendant à l’adresse https://{{vsts_account_name}}.visualstudio.com/_details/security/tokens

Finalement, l’agent pool doit être un pool pré-existant. A vérifier/créer ici : https://{{vsts_account_name}}.visualstudio.com/_admin/_AgentPool

Petit plus, dans le cas ou vous envisagez de builder des projets front, profitez de cette étape pour ajouter l’artefact NODE JS.

Bon, aller y’a plus qu’a cliquer sur OK, attendre quelques minutes et l’agent devrait apparaitre dans le pool que vous avez choisi.

Quoi qu’il en soit pas de panique, si vous vous êtes trompé sur un paramètre des artefacts, il sera toujours possible de retenter l’installation a postériori ou bien de procéder a l’installation manuellement.

Dernier point, si vos crédits azure ne vous permettent pas de laisser cette vm allumée tout le temps, voici deux petites commandes qui vous permettront d’allumer et d’éteindre la vm a volonté. (a utiliser dans une console azure cli

az lab vm {{command}} --lab-name {{devtestlab}} --name {{vm-name}} --resource-group {{resource-group}}

command : start ou stop
devtestlab : le nom de votre instance DevTest lab
vm-name : le nom de votre vm
resource-group : le nom du resource group ou est installé la vm.

]]>
<![CDATA[OData & ngTable : un duo de choc]]>

Dernièrement, j’ai pas mal fait joujou avec OData.
C’est quand même super plaisant de pouvoir requêter une source de données via une URL et avec une richesse proche de ce que l’on connait avec du SQL.
Une fois n’est pas coutume je ne vais pas parler

]]>
http://www.mymemoryleaks.fr/odata-ngtable-un-duo-de-choc/5a99b626f336bf15fc91af7fMon, 12 Dec 2016 11:46:00 GMT

Dernièrement, j’ai pas mal fait joujou avec OData.
C’est quand même super plaisant de pouvoir requêter une source de données via une URL et avec une richesse proche de ce que l’on connait avec du SQL.
Une fois n’est pas coutume je ne vais pas parler de .NET mais plutôt partager avec vous un bout de javascript qui met en évidence la facilité avec laquelle vous pourrez brancher des tables ngtable avec votre backend odata.

Trêve de bavardage, on passe au code :

Pour cette illustration, j'ai utilisé le web service services.odata.org qui expose la base Northwind (sample Microsoft) que l'on a tous croisés un jour.

Juste un mot sur le code, évidemment c'est le service odataTableService qui fait la glue entre OData et ngTable; c'est lui qui permet de réaliser les filtrages et les sorts. Une fois que ce service est disponible dans votre app, regardez avec quelle simplicité, votre controller peut créer une table :

$scope.tableParams = odataTableService.createTableParams({ endPoint: 'http://services.odata.org/V3/Northwind/Northwind.svc/Products' });

Je me demande vraiment pourquoi OData n'a pas plus que ça le vent en poupe.

]]>
<![CDATA[Packager un projet SQL pour Octopus]]>

Que ce soit manuellement ou de manière automatique, lorsque l'on parle de déploiement il va nous falloir définir un package de déploiement.

Dans l'univers Octopus, les packages de déploiement sont des fichiers avec une extension .nupkg. Voyons comment en créer un pour un projet de Base de données.

Ajouter une

]]>
http://www.mymemoryleaks.fr/packager-un-projet-sql-pour-octopus/5a99b626f336bf15fc91af7eThu, 01 Sep 2016 20:07:00 GMT

Que ce soit manuellement ou de manière automatique, lorsque l'on parle de déploiement il va nous falloir définir un package de déploiement.

Dans l'univers Octopus, les packages de déploiement sont des fichiers avec une extension .nupkg. Voyons comment en créer un pour un projet de Base de données.

Ajouter une dépendance vers Octopack

Octopack est l’utilitaire que nous allons utiliser pour générer ce package de déploiement. Démystifions le terme, octopack produit un fichier qui n’est autre qu’un zip, contenant les fichiers à déployer ainsi qu’un ensemble de métadonnées et potentiellement des scripts powershell.
Bref, rien de bien extraordinaire.

Pour l’installer dans notre projet de base de données, nous allons utiliser Nuget, qui est un gestionnaire de dépendances très performant et bien connu des développeurs. Cependant il n’est pas facilement accessible lorsqu’on travailler sur un projet SQL/SSIS/SSRS/SSAS.

Pour tromper Visual Studio nous allons commencer par ajouter un projet C# de type console pour faire simple

Ajoutons sur ce projet C# une dépendance vers Octopack.

Dans la nouvelle fenêtre on cherche le package Octopack, et on l’installe.

Après avoir acquitté la fenêtre de preview d’install, la fenêtre «Output» de visual Studio devrait vous confirmer que l’installation s’est bien passée.

Il aurait été formidable de pouvoir l’installer directement dans notre projet de base, mais nous allons devoir transpirer un peu plus pour arriver à nos fins.
Ready ?? Ouvrons le fichier csproj de l’application console et copions la portion de msbuild qui correspond à Octopack

Puis, copions la discrètement dans notre fichier sqlproj, de la même manière à la fin de celui-ci.
Un petit rebuild pour vérifier que tout fonctionne toujours bien… et TADAM y’a toujours pas de package de déploiement généré.

Créer le package

Bon si vous avez été un peu curieux, vous aurez remarqué que la portion de msbuild que l’on a copiée a pour but d’importer un autre fichier msbuild (qui se trouve dans le répertoire packagesOctoPack.3.4.1toolsOctoPack.targets)

En baragouinant un peu le msbuild, on comprend assez vite que la variable RunOctoPack est initialisée à false et c’est elle qui déclenche ou non la génération du package.

Alors évidemment, une solution possible est de modifier cette variable à true. Néanmoins cela induit qu’un package de déploiement sera créé a chaque build du projet. Ce n’est vraisemblablement pas ce que vous souhaitez.

Je vous propose plutôt d’ouvrir une console DOS et une fois dans le répertoire du projet, tapez la commande suivante :

msbuild ContinuousBI.Sql.sqlproj /t:Build /p:RunOctoPack=true

Si tout s’est bien passé vous devriez avoir une sortie similaire a celle-ci :

Cette fois ci, si vous jetez un œil dans le sous-dossier obj/octopacked de votre projet vous y découvrirez un fichier .nupkg qui est le package de déploiement

A quoi ressemble mon package ?

Pour aller un peu plus loin nous pouvons jeter un œil à ce qui a été produit pour nous par Octopack.
Je vous propose d’utiliser nuget package explorer
Ouvrez le et glissez déposez le fichier .nupkg, vous devriez obtenir un résultat semblable à celui-ci.

C’est confirmé, le dacpac issu de la compilation à bien été reconnu ; il est embarqué dans package de déploiement.

Nous verrons dans le prochain post comment le déployer avec Octopus.

]]>
<![CDATA[Prolific usb to ttl et windows 10]]>

Dernièrement j'ai ressorti ma BeableBone Black histoire de faire une peu de veille techno. J'vous raconterai un de ces quatre en quoi monter une boite peut vite cramer tout votre temps libre, mais c'est pour la bonne cause.

Bref pour en revenir à la Beagle, je ressors mon câble série

]]>
http://www.mymemoryleaks.fr/prolific-usb-to-ttl-et-windows-10/5a99b626f336bf15fc91af7dWed, 11 May 2016 21:34:00 GMT

Dernièrement j'ai ressorti ma BeableBone Black histoire de faire une peu de veille techno. J'vous raconterai un de ces quatre en quoi monter une boite peut vite cramer tout votre temps libre, mais c'est pour la bonne cause.

Bref pour en revenir à la Beagle, je ressors mon câble série que j'utilise pour me connecter à la console. Je fais les branchements et go sur le site de Prolific pour récupérer le dernier driver pour Windows 10.

Tiens! bizarre, même après un reboot je n'ai toujours rien qui s'affiche dans mon terminal.
En creusant, je m'aperçois que le driver du câble n'est pas reconnu.

S'en suit plusieurs tentatives de réinstallation et de reboot infructueuses.

Je cherche un peu sur Internet, pas mal de personnes ont des soucis avec des versions contrefaites acheté sur des sites asiatiques. Le mien vient de chez Adafruit, et il fonctionnait parfaitement il y a quelques mois, sur Windows 8.

Ho... tiens réessayons sur cet ancien PC. Ca fonctionne parfaitement!
Énorme je récupère l'installer du driver qui se trouve sur ce dernier;
Je repasse sur mon PC équipé de Windows 10, désinstalle le driver en place, reboot, installe l'ancien driver (fonctionnant sur Windows 8) et surprise, ca fonctionne.

Si ça c'est pas de l'obsolescence programmée! Honteux!
Rien que pour ça, je vous recommande plutôt d'investir dans un câble concurrent comme ce FTDI. J'en possède un également et fonctionne tout aussi bien.

Du coup, je vous dépose le driver fonctionnel, ici. J'espères que cela pourra aider quelqu'un.

Tiens, en prime je poste ici le schéma de branchement du câble Prolific avec la beagle.

  • Le fil noir va sur le pin 1 (GND)
  • le fil vert sur le pin 4 (RECEIVE)
  • le fil blanc sur le pin 5 (TRANSMIT)

Ne branchez surtout pas le fil rouge, c'est du 5V, vous grilleriez la beagle!!

]]>
<![CDATA[Comment invoquer une méthode dont on connait le nom à l’exécution sur un dynamic?]]>

Comment invoquer une méthode dont on connait le nom à l'exécution sur un dynamic?

Le mot clé dynamic en C# n'est pas nouveau, il a vu le jour avec C# 4 et pourtant il n’apparaît pas si souvent que ça dans les bouts de code que je fréquente.

Dernièrement

]]>
http://www.mymemoryleaks.fr/comment-invoquer-une-methode-dont-on-connait-le-nom-a-lexecution-sur-un-dynamic/5a99b626f336bf15fc91af78Fri, 24 Jul 2015 12:51:00 GMT

Comment invoquer une méthode dont on connait le nom à l'exécution sur un dynamic?

Le mot clé dynamic en C# n'est pas nouveau, il a vu le jour avec C# 4 et pourtant il n’apparaît pas si souvent que ça dans les bouts de code que je fréquente.

Dernièrement je l'ai recroisé en utilisant SignalR; les hubs qui sont générés sont des objets dynamic.

Quoi qu'il en soit, dernièrement j'ai eu besoin d'invoquer une méthode dont le nom ne m'était connu qu'à l'exécution.
Croyez-moi, j'y ai passé un petit moment avant d'y arriver... Cela révèle vraisemblablement ma grande ignorance 🙂

Ce blog post prendra donc la forme d'un post-it qui me fera gagner du temps la prochaine fois que je me frotterai a cette bête-là. Si pour vous les classes Binder et CallSite n'ont plus de secret ce blog post vous semblera vraisemblablement bien terne.

Posons le problème, on me donne un objet dynamic auquel une méthode est ajoutée à l'exécution

private string sentence = "Hello world"; public dynamic BuildObj() { dynamic myDynObj = new ExpandoObject(); myDynObj.SayHello = new Func(() => sentence); return myDynObj; }

Si j'avais connaissance de la méthode lors de la compilation je pourrais l'appeler ainsi :

[Test] public void CallDirectlyMethod() { dynamic myObj = BuildObj(); var ret = myObj.SayHello(); Assert.That(ret, Is.EqualTo(sentence)); }

Malheureusement la signature de la méthode ne m'est connue qu'à l'exécution.
Ok, premier réflexe je sors l'attirail de la reflection.... mais les résultats restent catastrophiques :

[Test] public void CallMethodWithReflectionFails() { dynamic myObj = BuildObj(); Type t = myObj.GetType(); var method = t.GetMethod("SayHello", BindingFlags.Default | BindingFlags.Instance | BindingFlags.InvokeMethod | BindingFlags.NonPublic); Assert.That(method, Is.Null); }

Quels que soient les bindings flags, impossible de trouver la méthode... FAIL!!

Voici, donc la combinaison magique, un savant mélange de Runtime.Binder et CallSite...

[Test] public void CallMethodWithCallSite() { dynamic myObj = BuildObj(); var callSiteBinder = Binder.InvokeMember(CSharpBinderFlags.None, "SayHello", Enumerable.Empty(), myObj.GetType(), new [] { CSharpArgumentInfo.Create(CSharpArgumentInfoFlags.None, null) }); var callSite = CallSite<Func<CallSite, object, object>>.Create(callSiteBinder); string ret = callSite.Target(callSite, myObj); Assert.That(ret, Is.EqualTo(sentence)); }

Ok, essayons de décrypter un peu ce code qui semble un peu alambiqué.
Binder.InvokeMember va nous permettre à l'exécution de pointer la bonne méthode un peu comme le ferait typeof(myObj).GetMethod()
Le premier paramètre permet de spécifier la manière dont est traité le type de retour. Dans le cas d'une Action nous aurions pu utiliser CSharpBinderFlags.ResultDiscarded. Dans notre cas, une Func, CSharpBinderFlags.None fonctionne bien.

puis viens en seconde position, évidement le nom de la méthode a appelé, passée sous forme de chaine.

En troisième position, il conviendra de fournir la liste des arguments de types à nécessaire dans le cas d'une méthode générique.

Viens ensuite le type sur lequel effectuer l'invocation, ce qui permet de pointer une surcharge.

Et finalement les informations sur les paramètres attendus et le type de retour (le premier élément du tableau);

La création du CallSite<Func<CallSite, object, object>> permet d'arrêter la signature du delegate que l'on cherche à appeler. Notez, que le dernier argument générique "object" devrait etre "string", car il représente le type de retour de la func... mais pour une raison qui m'échappe l'utilisation de string comme type de retour entraîne une erreur au runtime, alors que le retour de la func est bien affecté à une variable string à la ligne du dessous... il faut bien garder un peu de magie 🙂

Ok, évidemment il ne nous reste plus qu'à effectuer l'invocation, ce qui est réalisé via le code callSite.Target(callSite, myObj);

J'espère que ce post évitera quelques cheveux blancs a ceux qui se trouveront confronté au problème.

]]>
<![CDATA[BeagleBone Black du carton à Mono]]>

L’IOT, on en parle partout, de plus en plus ; évidemment l’univers Microsoft n’est pas en retrait sur ce domaine avec la mise à disposition de Windows 10 sur le Raspberry ou encore le MinnowBoard MAX

Vous trouverez pas mal de blog post autour du raspberry… je vais

]]>
http://www.mymemoryleaks.fr/beaglebone-black-du-carton-a-mono/5a99b626f336bf15fc91af77Mon, 01 Jun 2015 10:31:00 GMTBeagleBone Black du carton à Mono

L’IOT, on en parle partout, de plus en plus ; évidemment l’univers Microsoft n’est pas en retrait sur ce domaine avec la mise à disposition de Windows 10 sur le Raspberry ou encore le MinnowBoard MAX

Vous trouverez pas mal de blog post autour du raspberry… je vais donc plutôt vous présenter comment vous lancer dans le développement .NET embarqu& sur cette magnifique plateforme qu’est le BeagleBone Black (BBB). Au travers de cet article je vous propose d’étudier les différentes étapes à réaliser pour pouvoir lancer votre premier « Hello World » embarqué.

BeagleBone Black du carton à Mono

Tout d’abord il n’y a pas de Windows 10 sur le BBB, en tout cas pour l’instant, mais très honnêtement l’installation d’Ubuntu que je vous propose est à la portée de tous.

Matériel nécessaire

Je commence par un petit coup de pub pour le site AdaFruit ou vous trouverez tout le matos que vous pouvez imaginer pour nos petits joujoux.

Aller Go ! Pour faciliter la visualisation de ce qui se passe sur votre BBB je vous conseille d’investir dans un câble Serial TTL-232 en usb. Sans celui-ci vous devrez attendre que le BeagleBone ai récupéré une IP et vous y connecter (en ssh par exemple) et interagir avec.

Pour brancher le câble prenez comme repère le fil noir qui doit venir se placer sur le pin J1 de votre BBB.

Installez les drivers FTDI pour prendre en compte l’adaptateur usb. Ils se trouvent ici

Finalement en utilisant Putty, configuré comme ci-dessous la console s’affiche enfin sur votre pc.

BeagleBone Black du carton à Mono

Si l’idée de brancher un câble Ethernet sur votre BeagleBone vous donne de l’urticaire, je vous conseille ce dongle usb. Il est directement reconnu sous Ubuntu.

Installation d’Ubuntu

BeagleBone Black du carton à Mono

Nous allons installer dans la mémoire eMMC la version 14.04 d’Ubuntu spécialement conçue pour la BBC. Après avoir téléchargé le fichier img.xz, il vous faudra le décompresser avec un outil comme 7zip.

L’image ainsi extraite pourra être copiée sur une micro sd avec Win 32 Disk Imager

Lorsque la copie se termine, insérer la micro sd dans le port prévu à cet effet sur la BBB. Tout en appuyant avec votre index sur le bouton « boot » (le plus proche du port Ethernet), alimentez la BeagleBone. Laissez le doigt appuyé jusqu’à ce que les diodes clignotent.

Il faut 5 bonnes minutes pour que l’installation se termine ; mais grâce au câble TTL vous serez aux premières loges pour suivre l’installation.

Mise à jour du Système et installation de mono

Ok, si vous en êtes arrivé là, c’est du tout cuit.

Nous allons commencer par mettre à jour le système grâce package manager APT. A partir de la console tapez les commandes suivantes :

sudo apt-get update sudo apt-get upgrade

Après quelques minutes le système est prêt, on peut passer à Mono. Le runtime devrait être suffisant étant donné que l’on va se contenter d’exécuter des binaires créer sur votre machine de dev. Pour l’installation on tape donc :

sudo apt-get install mono-runtime

Création de l’exécutable et déploiement sur le BBB

Je vous laisse écrire votre premier Hello Beagle World dans Visual Studio ; en créant un projet de type console et en targettant le Framework 4.5;

Une fois compilé, j’ai opté pour un déploiement type « bin-deploy » en utilisant un transfert via PSCP

Une fois PSCP copié, vous pourriez copier le fichier avec une ligne de commande comme celle-ci :

pscp.exe "C: BBB HelloWorldbinDebugHelloWorld.exe" ubuntu@192.168.10.2:/home/ubuntu

Le premier paramètre étant le ficher à transmettre le second l’url de destination au format :

user@hote:/chemin_de_destination

En dessert, après tous ces efforts, nous pouvons enfin exécuter sur le Beagle notre Hello World en tapant :

Mono HelloWorld.exe

]]>
<![CDATA[Kibana : Explorez vos données.]]>

Cet article fait partie d’une sérié dédiée à Elasticsearch, reportez vous à l’article sommaire pour accéder facilement aux autres posts.

Kibana est la brique de visualisation qui gravite autour d’Elasticsearch. Voici, quelques exemple de représentations faites avec Kibana :





Kibana 2


Kibana 3

L’exploration de données et la réalisation de dashboard

]]>
http://www.mymemoryleaks.fr/kibana-explorez-vos-donnees/5a99b626f336bf15fc91af76Tue, 23 Dec 2014 09:39:00 GMTKibana : Explorez vos données.

Cet article fait partie d’une sérié dédiée à Elasticsearch, reportez vous à l’article sommaire pour accéder facilement aux autres posts.

Kibana est la brique de visualisation qui gravite autour d’Elasticsearch. Voici, quelques exemple de représentations faites avec Kibana :


Kibana : Explorez vos données.


Kibana : Explorez vos données.


Kibana : Explorez vos données.

L’exploration de données et la réalisation de dashboard ne nécessitent aucun code, ce qui permet de donner la main aux fonctionnels ; De plus Kibana et Elastocsearch permettent d’avoir des rapports real time, se mettant à jour à mesure que les données sont stockées.

Pour les lecteurs qui connaissent bien la stack SQL Serveur, on pourrait le comparer à un Report Builder sous stéroïdes et surtout qui tiendrait (mieux) ses promesses de simplicités et d’accessibilité pour les non-techniciens

Je me propose dans ce billet de découvrir ensemble les fonctionnalités de « data discovering » sur un dataset public recensant les accidents corporels de la circulation

Si ces données vous intéressent, je vous invite d’ailleurs à jeter un œil à la très bonne session (video, slides) de Patrice Harel sur le mining avec SSAS et qui s’appui sur le même jeu de données.

Installation

Commençons par l’installation qui comme pour les autres composants de la stack est triviale :
Tout commence évidement par le téléchargement du binaire ici, suivi de la décompression de l’archive.
Si votre instance elasticsearh ne tourne pas sur le même serveur qui hébergera Kibana ou si elle écoute sur un port non standard, il vous faudra modifier le fichier de configuration config/kibana.yml.
Dans mon cas, je ne touche à rien!
Puis à l’aide d’une fenêtre commande, il nous faudra exécuter /bin/kibana après s’être placé dans le répertoire ou a été décompressé l’archive.
Finalement pointons notre navigateur sur l’url http://localhost:5601

Exploration

S’il s’agit de la première fois que vous lancez Kibana, cet écran vous sera présenté, dans lequel il vous faudra choisir un index (équivalent de base de données) ainsi qu’une colonne typée date.
Ce dernier point est extrêmement important, car Kibana part du principe qu’il est naturel pour l’esprit humain et plus facile de découvrir des données lorsqu’elles sont représentées sur une frise.

Kibana : Explorez vos données.

Dans notre dataset, nous ne disposons malheureusement pas de la date de l’accident, qui aurait été le candidat idéal en tant que « time field ».
Pour l’exemple, nous nous rabattrons sur le champ @timestamp représentant l’instant ou a été inséré l’événement dans notre index.

On se retrouve propulsé dans nos données via l’écran suivant :

Kibana : Explorez vos données.

On reconnait très vite plusieurs sections dans cette interface :

  • La colonne de gauche qui contient les champs à disposition (1).
  • Tout en haut (2), une zone de filtre ; n’oublions pas qu’elasticsearch est un moteur de recherche…
  • L’indicateur du nombre d’enregistrements après filtrage (3).
  • La frise temporelle sur laquelle on regarde les événements (4).
  • Finalement la vue tableau de données au centre. Notons que pour l’instant elle nous représente la version brute des données, car nous n’avons pas encore choisit de colonnes à afficher.

Commençons par cliquer sur les barres du graph afin d’effectuer un drilldown au niveau temps.

Kibana : Explorez vos données.

Instantanément cela nous permet de découvrir la répartition des data dans le temps. Notez, que les clics que nous avons fait sur le graph sont interprétés comme une clause de filtrage, diminuant les événements auxquels on s’intéresse.

Pour avoir un aperçu du contenu des champs, je vous conseille de cliquer sur le nom d'un champ dans la colonne de gauche ; comme ceci :

Kibana : Explorez vos données.

Les informations et actions présentées ici sont une vraie mine d’or.
En plus d'un premier comptage des données sous-jacentes, on peut par exemple se concentrer sur les événements qui ont eu lieu sur l’A31 en cliquant sur l'icone loupe+. Evidemment, la frise temporelle et les données sont mis à jour.

Kibana : Explorez vos données.

Maintenant, intéressons nous au champ tbl qui représente le nombre de blessés légers dans un accident.

Kibana : Explorez vos données.

En cliquant sur « Visualize », on obtient la répartition top 20, sous forme d’histogramme, du nombre de blessés légers sur l’ensemble des événements de la base.

Kibana : Explorez vos données.

Ici aussi cette visualisation, nous permet d’appréhender rapidement la teneur de nos données.

Finalement jetons un œil, au filtre qui se trouve tout en haut de l’interface de Kibana. Par défaut, vous y trouverez une *. Attention, il n’y a pas ici d’analogie avec SQL, ici l’étoile signifie sans filtre.
Nous pourrions par exemple nous intéresser à une commune en particulier, celle de Cergy par exemple (95002). Il nous suffira pour ce faire de saisir le filtre suivant :

codeinsee:=95002


Kibana : Explorez vos données.

Ou bien les accidents impliquant plus de 2 morts

ttué:>2


Kibana : Explorez vos données.

Ou encore les accidents impliquant plus de 2 morts dans l’Oise :

ttué:>2 AND codeinsee [60000 TO 69999]


Kibana : Explorez vos données.

Voila qui clos ce premier article sur Kibana, en espérant vous avoir donné envie d’essayer ce superbe outil.

]]>
<![CDATA[Série Elasticsearch]]>

Ce post fait office de sommaire à toute une série d’articles que j’ai bon espoir d’écrire sur cette toute fin d’année 2014 et le début 2015.

Mais pourquoi parler d’Elasticsearch, moi qui ne traite que de technos Microsoft sur ce blog?

Cela part du constat

]]>
http://www.mymemoryleaks.fr/serie-elasticsearch/5a99b626f336bf15fc91af75Tue, 23 Dec 2014 09:37:00 GMT

Ce post fait office de sommaire à toute une série d’articles que j’ai bon espoir d’écrire sur cette toute fin d’année 2014 et le début 2015.

Mais pourquoi parler d’Elasticsearch, moi qui ne traite que de technos Microsoft sur ce blog?

Cela part du constat qu’a mon humble avis, la stack BI Microsoft pèche sur deux points :

  • Premièrement, il n’existe pas d’outils permettant une exploration décente des données non encore nettoyées, rangées, retraitées etc.… d’ailleurs, plus la volumétrie est importante et plus ce point est difficilement adressable.
    (i.e : sur de petites volumétries, j’en entends déjà me dire qu’Excel peut avoir ce rôle, avec un enchevêtrement de tableaux croisés dynamiques etc… )
  • L’outillage de reporting est assez pauvre et n’est vraiment pas penser pour être à destination des fonctionnels.
    Je m’explique Reporting Services fait le job lorsqu’il s’agit de réaliser un document pro format, mais nécessite des compétences techniques que nos fonctionnels ne disposent pas ; et c’est bien normal.
    Vous aurez probablement également entendu parler de la version « User Friendly » de « Reporting Services », j’ai nommé Report Builder. La tentative est louable, mais le résultat n’est pas la à hauteur.
    Encore une fois dans les faits, bien peut de fonctionnels ont les connaissances, l’envie et le temps de l’utiliser.

C’est avec ces regrets dans l’âme, que je me retrouve lors de la conférence ncraft 2014 à assister à une superbe session d’Itamar Syn-Hershko consacrée au couple Elasticsearch et Kibana.

Je vous passe les détails de cette présentation, mais effet whaou garanti vers la fin de la session lorsque Kibana rentre en scène.

Certain doivent se dire qu’il m’a fallu presque 1 an pour commencer à sortir un article, quelle productivité !

Pour être tout à fait franc, il y a 1 an il manquait encore quelques features indispensable a mon sens pour que Kibana puisse jouer un rôle aussi important que ce pour quoi il à été conçu. L’exemple le plus probant était l’impossibilité de réaliser un « distinc count » ; un « show stopper » pour qui compte faire un peu de BI sérieusement.

Voila pour le petit historique et mes états d’âmes ; Kibana est arrivé à maturité selon moi dans ses cas d’utilisation standard et cela mérité bien qu’on s’y intéresse ainsi qu’a l’écosystème qui gravite autour.

Voici enfin l’heure du menu :

  • 1ere Partie : Explorez vos données avec Kibana
  • 2eme Partie : Chargez vos données, les yeux fermés avec Logstash
  • 3eme Partie : Introduction à Elasticsearch
  • 4eme Partie : Changement de mapping et Reindexation
  • 5eme Partie : Reporting avancé & Dashbording (Kibana)
  • 6eme Partie : Transformation de données (Logstash)

Il y’a de forte chance que ce sommaire soit agrémenté d’autres articles dans le futur ; le domaine étant extrêmement large.

Dernier point, l’ordre des premiers articles peut vous paraître étrange ; j’ai voulu partir de ce qui apportera le plus de valeur ajouté aux fonctionnels pour finir par ce qui requiers le plus de compétences techniques.

Il ne me reste qu'a vous souhaiter une bonne lecture, et n'hésitez pas a me laisser vos commentaires.

]]>
<![CDATA[Utiliser Couchbase comme serveur de cache]]>

Dernièrement, je vous présentais une façon simple d'utiliser le cache dans vos applications .NET
Cependant cette solution possède plusieurs inconvénients. En voici quelque uns :

  • Le cache est lié au processus système de votre application (executable / IIS etc...). Si votre programme plante ou est fermé, vous perdez votre cache
  • Si vos
]]>
http://www.mymemoryleaks.fr/utiliser-couchbase-comme-serveur-de-cache/5a99b626f336bf15fc91af74Fri, 11 Apr 2014 13:13:00 GMTUtiliser Couchbase comme serveur de cache

Dernièrement, je vous présentais une façon simple d'utiliser le cache dans vos applications .NET
Cependant cette solution possède plusieurs inconvénients. En voici quelque uns :

  • Le cache est lié au processus système de votre application (executable / IIS etc...). Si votre programme plante ou est fermé, vous perdez votre cache
  • Si vos besoins en mémoire augmentent, cette solution n'est pas scalable
  • Rien n'est mis a disposition pour monitorer votre cache
  • Vous n'avez pas d'interface de gestion du cache (augmentation de la mémoire allouée etc...)
  • Vous ne pouvez pas invalider le cache sans arrêter l'application.
  • etc...

Bref, vous avez compris, c'est une solution pour démarrer petit.

Aujourd'hui, je voudrais partager avec vous une solution qui répond à tous les manques évoqués plus haut et plus encore.
Couchbase est une base NoSQL Key/Value; la value ayant comme particularité d'être un document json.
Couchbase est issu du mariage heureux de Membase (cache mémoire avec réplication des caches, persistance et interface d’admin Web sexy) et
CouchDB (NoSQL orienté document). Ce qui nous intéresse plus particulièrement aujourd'hui sont les fonctionnalités qui en font un bon serveur de cache.

Installation

Pour l'installer, tout commence par télécharger le setup ici

Je vous passe le scénario d'installation qui a le bon gout de se faire en "Next" > "Next" > "Next"

Passons à la configuration :

Dans la première étape, il vous faudra spécifier l'emplacement des fichiers (base et index) ainsi que la mémoire dévolue à Couchbase.

Utiliser Couchbase comme serveur de cache

Un peu plus loin nous allons créer le l'espace qui accueillera les objets que l'on va mettre en cache (bucket).

Utiliser Couchbase comme serveur de cache

Quelques instant plus tard vous voila avec un Couchbase flambant neuf sur votre machine.

Utiliser Couchbase comme serveur de cache

Note : si la page ne s'ouvre pas automatiquement dans votre browser, la console d'admin de couchbase se trouve a l'adresse suivante : http://localhost:8091/

Implementation

Couchbase dispose d'un très bel écosystème qui gravite autour, et la plateforme .NET ne fait pas exception.
Je me propose d'adapter le cache manager vu dans le précédent article.
Pour rappel nous avions l'interface suivante :

public interface ICacheManager { T GetOrInsert(string key, Func callback) where T : class; }

Passons à l'implémentation. Il va nous falloir un driver, que l'on peut aisément installer via nuget :

Utiliser Couchbase comme serveur de cache

son utilisation est des plus simple, avec des méthodes explicites comme Get() et Store().
Voici une implémentation de cache respectant notre interface basée sur Couchbase.

public class CouchbaseCacheManager : ICacheManager { private readonly CouchbaseClient _client; public CouchebaseCacheManager() { _client = new CouchbaseClient(); } public T GetOrInsert(string key, Func callback) where T : class { T elmnt; try { if (_client.KeyExists(key)) return _client.Get(key); elmnt = callback(); _client.Store(StoreMode.Add, key, elmnt); } catch (Exception) { elmnt = callback(); } return elmnt; } }

Et vous, quel type de cache utilisez vous dans vos projets?

]]>
<![CDATA[Poor man's cache]]>

Depuis la version 4 du framework .NET, la gestion d'un cache est profondement encrée dans l'adn de notre framework.
Il devient alors extrêmement facile de stocker en mémoire à peu près n'importe quoi.
Je vous livre dans ce court billet, une implémentation extrêmement simple que j'utilise souvent dans mes projets.

]]>
http://www.mymemoryleaks.fr/poor-mans-cache/5a99b626f336bf15fc91af73Fri, 04 Apr 2014 15:10:00 GMT

Depuis la version 4 du framework .NET, la gestion d'un cache est profondement encrée dans l'adn de notre framework.
Il devient alors extrêmement facile de stocker en mémoire à peu près n'importe quoi.
Je vous livre dans ce court billet, une implémentation extrêmement simple que j'utilise souvent dans mes projets.
Commençons par définir une interface, qui nous permettra d'injecter notre cache manager un peu partout :

public interface ICacheManager { T GetOrInsert(string key, Func callback) where T : class; }

et finalement voici une implémentation extra simple de notre cache manager

public class CacheManager : ICacheManager { public T GetOrInsert(string key, Func callback) where T : class { ObjectCache cache = MemoryCache.Default; if (cache.Contains(key)) return cache[key] as T; T elmnt = callback(); cache.Add(new CacheItem(key, elmnt), new CacheItemPolicy()); return elmnt; } }

Voici un exemple d'utilisation.

IEnumerable products = _cache.GetOrInsert("Ma_Clef_Unique_Cache", () => { return _productService.GetFrenchProducts(); } );

Simple non?

]]>