Bienvenue à Blogs CodeS-SourceS Identification | Inscription | Aide

Abonnements

EDMDesigner v2 : PRISM et Unity

Suite aux remarques de Thomas et John, ce post a été mis à jour.

Certains d’entre vous le savent, je suis en train de redévelopper mon EDM Designer.

Tout d’abord, la première version était mon premier projet WPF et si je devais le faire aujourd’hui, il est évident que je ne procèderais pas de la même façon (à l’époque, je n’avais pas utilisé MVVM par ex).

De plus, ma première version n’était pas autonome. Il fallait dans un premier temps récupérer l’edmx généré à partir d’une base de données avec VS et ensuite seulement on pouvait travailler avec mon designer

A cela, il faut rajouter que ma version se basait sur EF v1 (EF4 n’existant pas encore à l’époque).

J’ai donc décidé de repartir d’une feuille blanche et de proposer de nombreuses nouvelles fonctionnalités qui, je suis sûr, ne manqueront pas de vous ravir mais dont je garde le secret pour l’instant. Clignement d'œil // A ce propos, n’hésitez pas à me soumettre vos idées.

Parce que je trouve certains points de mon dev intéressants mais également parce que je suis friand de critiques constructives, j’ai décidé de ne pas développer seul dans mon coin mais de faire une série de post afin de vous faire partager les choix que j’ai pu faire et recueillir vos avis sur ceux-ci.

L’idée que je vais développer dans ce post est de rendre mon EDM Designer le plus modulaire possible afin de pouvoir

  • développer un module par version d’Entity Framework sans tout redévelopper à chaque nouvelle version
  • permettre de choisir dans l’application la version d’Entity Framework que l’on souhaite utiliser
  • donner la possibilité d’intégrer d’autre base de données que SQL Server
  • permettre d’externaliser la gestion du pluralize / singularize
  • etc.

Pour l’aspect modulaire, j’ai utilisé PRISM couplé avec Unity.

Plusieurs personnes m’ont dit que PRISM et Unity c’était des trucs pour la “branlette intellectuelle” d’architecte. Je vais donc tenter à travers cet article de leur prouver le contraire.

Unity est particulièrement utile pour mocker nos classes. Cependant, dans mon cas, je ne vais pas l’utiliser pour cela.

Avant de regarder plus en détail la solution que je propose, voici la vision du solution explorer :

image

Dans mon cas je vais utiliser PRISM pour définir les versions d’Entity Framework disponible dans mon application : en l’occurrence, EF v1 et EF 4.

Pour cela, je vais définir les modules que je veux utiliser dans mon App.config :

  
    
      
        <
      
    
    
      
        configuration
      
    
  
  
    
      
        >
        
  <
configSections
>
    <
section   name = "modules"
             type="Microsoft.Practices.Composite.Modularity.ModulesConfigurationSection, Microsoft.Practices.Composite"
/>
  </
configSections
>
  <
modules
>
    <
module   assemblyFile = "EDM.v1.dll"
            moduleType="EDM.v1.Module, EDM.v1"
            moduleName="EDM.v1"
/>
    <
module   assemblyFile = "EDM.v4.dll"
            moduleType="EDM.v4.Module, EDM.v4"
            moduleName="EDM.v4"
/>
  </
modules
>
</
configuration
>

Dans le constructeur de la classe App, je vais faire appel à mon Bootstrapper :

  
    
      
        public
      
    
     App()
{
    new Bootstrapper().Run();
}

Dans mon Bootstrapper, j’utilise le UnityBootstrapper fournit par PRISM afin d’instancier chacun des différent modules puis de créer mon Shell et l’afficher :

  
    
      
        public
      
    
     class Bootstrapper : UnityBootstrapper
{
    protected override DependencyObject CreateShell()
    {
        ConfigurationModuleCatalog moduleCatalog = new ConfigurationModuleCatalog();
        Container.RegisterInstance<IModuleCatalog>(moduleCatalog);

        Container.RegisterType<IModuleManager, ModuleManager>();
        IModuleManager moduleManager = Container.Resolve<IModuleManager>();
        moduleManager.Run();



  
  
  
    
      
        Container.RegisterType<IShellViewModel, ShellViewModel>();
        Shell shell = Container.Resolve<Shell>();
        shell.Show();

        return shell;
    }
}

J’utilise l’approche View First (ie : c’est la vue qui instancie le ViewModel). On pourrait croire que je fais du ViewModel first en voyant le code mais en réalité ce n’est pas le cas parce que j’utilise Unity.

  
    
      
        public
      
    
     partial class Shell : Window
{
    public Shell(IShellViewModel shellViewModel)
    {
        InitializeComponent();
        DataContext = shellViewModel;
    }
}

Dans mon cas, IShellViewModel étant associé avec ShellViewModel dans mon UnityContainer, lors de l’instanciation de mon Shell, unity va m’instancier un ShellViewModel pour le passer en paramètre.

Mon ShellViewModel va me retourner la liste des modules disponibles afin que je puisse les afficher dans une ListBox.

  
    
      
        <
      
    
    
      
        ListBox
      
      
         x
      
      
        :
      
      
        Name
      
      
        =
        "modulesLB"
      
      
        ItemsSource="{Binding Modules}"
        DisplayMemberPath="Name"
/>

  
    
      
        public
      
    
     interface IShellViewModel
{
    IEnumerable<EDMModuleBase> Modules { get; }
}

Comment récupérer la liste des modules ?

Le code que j’utilise est le suivant :

  
    
      
        public
      
    
     class ShellViewModel : IShellViewModel
{
    public ShellViewModel(Func<IEnumerable<IEDMModule>> modules)
    {
        Modules = modules();
    }

    public IEnumerable<IEDMModule> Modules { get; private set; }
}

Pour pouvoir l’utiliser il faut donc au préalable enregistrer les différents modules dans le container unity.

Je vais effectuer cette action dans le constructeur de mon module :

  
    
      
        public
      
    
     class Module : EDMModuleBase
{
    public Module(IUnityContainer unityContainer)
        : base(unityContainer)
    {
    }

    public override string Name
    {
        get { return "EDM v1"; }
    }
}

  
    
      
        public
      
    
     abstract class EDMModuleBase : IEDMModule
{
    public EDMModuleBase(IUnityContainer unityContainer)
    {
        unityContainer.RegisterInstance<EDMModuleBase>(Name, this);
    }

    public abstract string Name { get; }

    void IModule.Initialize()
    {
    }
}

  
    
      
        public
      
    
     interface IEDMModule : IModule
{
    string Name { get; }
}

Ainsi mes deux modules sont bien ajoutés dans le UnityContainer  lors de leur instanciation dans le Bootstrapper ce qui permet à mon ViewModel de les retrouver.

Maintenant, allons un peu plus loin.

La structure d’un EDM (avec une partie SSDL, une partie CSDL et partie MSL) est la même pour les versions 1 et 4 d’Entity Framework.

Aussi, je n’ai pas envie de redéfinir la classe EDM pour EF4. En revanche, le CSDL lui s’est enrichi avec EF4 (ajout des CSDL Functions). Du coup, je veux que ma classe EDM définie dans EDM.Base m’instancie un EDM.v4.CSDL quand j’utilise le Module v4 et un EDM.Base.CSDL quand j’utilise la v1.

Comment faire cela ?

Unity va bien nous aider.

En partant du UnityContainer principal, je vais définir un ChildContainer dans chacun des modules. Dans le ChildContainer du Module v4, je vais associer le type EDM.Base.CSDL avec le type EDM.v4.CSDL puis je vais rajouter une propriété EDM dans mon module qui sera créé par mon ChildContainer et la classe EDM va utiliser ce UnityContainer pour instancier le CSDL :

public  interface IEDMModule : IModule
{
    string Name { get; }
    EDM.Base.EDM EDM { get; }
}

  
    
      
        public
      
    
     abstract class EDMModuleBase : IModule
{
    public EDMModuleBase(IUnityContainer unityContainer)
    {
        unityContainer.RegisterInstance<EDMModuleBase>(Name, this);
        IUnityContainer childContainer = unityContainer.CreateChildContainer();
        Init(childContainer);
        EDM = childContainer.Resolve<EDM.Base.EDM>();
    }

    protected virtual void Init(IUnityContainer unityContainer)
    {
    }

    public abstract string Name { get; }

    public EDM.Base.EDM EDM { get; private set; }

    void IModule.Initialize()
    {
    }
}

  
    
      
        namespace
      
    
     EDM.v4
{
    public class Module : EDMModuleBase
    {
        public Module(IUnityContainer unityContainer)
            : base(unityContainer)
        {
        }

        protected override void Init(IUnityContainer unityContainer)
        {
            base.Init(unityContainer);
            unityContainer.RegisterType<Base.CSDL, CSDL>();
        }

        public override string Name
        {
            get { return "EDM v4"; }
        }
    }
}

  
    
      
        public
      
    
     class EDM
{
    public EDM(SSDL ssdl, CSDL csdl, MSL msl)
    {
        SSDL = ssdl;
        CSDL = csdl;
        MSL = msl;
    }

    public SSDL SSDL { get; private set; }
    public CSDL CSDL { get; private set; }
    public MSL MSL { get; private set; }

    public virtual IEnumerable<IEDMElement> EDMElements
    {
        get
        {
            yield return SSDL;
            yield return CSDL;
            yield return MSL;
        }
    }
}

Vérifions avec un petit exemple :

  
    
      
        <
      
    
    
      
        Grid
      
      
        >
      
      
    < Grid.ColumnDefinitions >
        < ColumnDefinition />
        < ColumnDefinition />
    </ Grid.ColumnDefinitions >
    < ListBox x : Name = "modulesLB"
            ItemsSource="{Binding Modules}"
            DisplayMemberPath="Name" />
    <Grid Grid.Column="1">
        <ListBox ItemsSource="{Binding SelectedItem.EDM.EDMElements, ElementName=modulesLB}" />
    </Grid
>
</
Grid
>

image

image

Ce post vous a plu ? Ajoutez le dans vos favoris pour ne pas perdre de temps à le retrouver le jour où vous en aurez besoin :

Publié samedi 27 novembre 2010 00:42 par Matthieu MEZIL

Classé sous : , , , ,

Commentaires

# re: EDMDesigner v2 : PRISM et Unity @ samedi 27 novembre 2010 11:24

Bon boulot !

Je ne sais pas dans quelle mesure ce projet pourrait être integré à SharpDevelop, mais c'est peut-être intéressant d'y penser. SD inclut en EF wizard.

:)

Graveen

# re: EDMDesigner v2 : PRISM et Unity @ samedi 27 novembre 2010 13:39

Bonjour Matthieu,

Pourquoi ne pas être parti sur MEF, pour la parties composition / injection ?

J'aime bien l'approche injection par Attribut que propose MEF, et le DirectoryCatalog pour le chargement du container est lui aussi assez sympa.

Qu'en pense tu ?

metaem

# re: EDMDesigner v2 : PRISM et Unity @ samedi 27 novembre 2010 14:56

@Graveen:

J'avais déjà été contacté par SharpDevelop pour la v1. Je leur avait dit qu'il pouvait utiliser mon designer sans pb. Je ne sais pas où ça en est. Mais c'est vrai que là ça sera beaucoup plus facilement intégrable du fait du découpage modulaire. D'ailleurs à terme, je compte proposer une version hostée dans VS.

@metaem:

Je ne suis pas parti sur MEF pour pouvoir définir une dépendance entre les modules. De plus, PRISM me permet de bénéficier de l'EventAggregator dont je parlerai plus tard.

Matthieu MEZIL

# re: EDMDesigner v2 : PRISM et Unity @ dimanche 28 novembre 2010 00:52

Hello Mathieu,

Juste une question. Pourquoi passer le containeur unity partout dans les classes? Ne peux tu injecter directement les dépendances dans les classes au lieu d'injecter Unity ?

Par exemple la classe EDM devrait à mon goût prendre en constructeur les classes CSDL, SSDL, MSL.

tja

# re: EDMDesigner v2 : PRISM et Unity @ dimanche 28 novembre 2010 08:47

@Thomas :

Dans ce cas-là oui tu aurais pu mais maintenant dans le CSDL quand tu dois créer des EntityTypes tu ne peux pas passer l'ensemble des EntityTypes en paramètre vu qu'on ne les connait pas encore.

Donc par soucis d'homogénéisation, je passe systématiquement le container Unity.

Matthieu MEZIL

# re: EDMDesigner v2 : PRISM et Unity @ lundi 29 novembre 2010 00:08

Salut Mathieu,

Je rejoint un peu la question de Thomas.

J'ai bien compris qu'on ne connaissait pas les EntityTypes au moment de la construction mais dans ce cas là ne serait-il pas un peu plus propre d'avoir un IEntityTypeLoader qui lui à la rigueur fait appel à Unity de façon à supprimer la dependence à Unity dans tout tes types ?

Je pense qu'avoir autant de dépendence à Unity pourra causer des soucis pas la suite.

grogru

# re: EDMDesigner v2 : PRISM et Unity @ lundi 29 novembre 2010 07:14

@John et Thomas :

Mais clair en fait. Je vais reprendre mon code du coup.

Voilà, je ne regrette pas d'avoir passé un peu de temps pour écrire ce post :)

Matthieu MEZIL

# re: EDMDesigner v2 : PRISM et Unity @ mercredi 1 décembre 2010 16:30

Salut Matthieu,

rien a redire sur le fond de l'article, très intéressant.

Par contre, pour ceux qui ne sont pas dans la confidence, tu ne voudrais pas nous dire au moins pour quelles raisons tu souhaites refaire un designer d'EDM?  Je n'ose croire que la seule raison qui te pousse à ca, soit de pouvoir faire de l'EF1 ou EF4...

fabrice.michellonet

# re: EDMDesigner v2 : PRISM et Unity @ jeudi 2 décembre 2010 00:08

Non c'est bien sûr pas ça ma motivation.

Le pb principal pour l'adoption d'EF selon moi c'est le designer qui est, je suis au regret de le dire, pourri !

Le TPC ou Horizontal Entity Splitting ne sont pas supportés, le Complex Type, à moitié.

Le designer n'est pas adaptée pour les "gros" modèles.

L'update du modèle suite à une modif de la base est potentiellement problématique. En effet, si on a modifié le SSDL, les modifs sont perdues.

etc, etc.

J'avais fait mon propre EDM Designer pour EF v1 afin de corriger une bonne partie de ces problèmes.

Le designer s'est amélioré avec VS 2010 mais n'est toujours pas à la hauteur. Du coup, plusieurs personnes, qui utilisaient mon EDM Designer v1, m'ont demandé de le porter sur EF4.

De mon côté, j'en profite pour tenter de relever ce challenge tout en utilisant des technos sympas même si le fait d'avoir un Kinect pénalise ma productivité ;)

Matthieu MEZIL

# re: EDMDesigner v2 : PRISM et Unity @ vendredi 10 décembre 2010 09:11

OK, merci pour l'explication.

Effectivement, Kinect a tendance a pénaliser la productivité de tout ceux qui passent à côté :).

Pour en revenir a EF, je partage avec toi la sensation que le Designer est perfectible; Du coup j'ai hâte de voir ce que tu vas nous proposer.

fabrice.michellonet

Les commentaires anonymes sont désactivés

Les 10 derniers blogs postés

- Merci par Blog de Jérémy Jeanson le 10-01-2019, 20:47

- Office 365: Script PowerShell pour auditer l’usage des Office Groups de votre tenant par Blog Technique de Romelard Fabrice le 04-26-2019, 11:02

- Office 365: Script PowerShell pour auditer l’usage de Microsoft Teams de votre tenant par Blog Technique de Romelard Fabrice le 04-26-2019, 10:39

- Office 365: Script PowerShell pour auditer l’usage de OneDrive for Business de votre tenant par Blog Technique de Romelard Fabrice le 04-25-2019, 15:13

- Office 365: Script PowerShell pour auditer l’usage de SharePoint Online de votre tenant par Blog Technique de Romelard Fabrice le 02-27-2019, 13:39

- Office 365: Script PowerShell pour auditer l’usage d’Exchange Online de votre tenant par Blog Technique de Romelard Fabrice le 02-25-2019, 15:07

- Office 365: Script PowerShell pour auditer le contenu de son Office 365 Stream Portal par Blog Technique de Romelard Fabrice le 02-21-2019, 17:56

- Office 365: Script PowerShell pour auditer le contenu de son Office 365 Video Portal par Blog Technique de Romelard Fabrice le 02-18-2019, 18:56

- Office 365: Script PowerShell pour extraire les Audit Log basés sur des filtres fournis par Blog Technique de Romelard Fabrice le 01-28-2019, 16:13

- SharePoint Online: Script PowerShell pour désactiver l’Option IRM des sites SPO non autorisés par Blog Technique de Romelard Fabrice le 12-14-2018, 13:01