EDM Designer v2: PRISM and Unity

Some of you know it, I’m coding a new version of my EDM Designer from scratch.

My first version was my first WPF project and I would not do it with the same way if I have to do it today (for example, I didn’t use MVVM).

Moreover, my first version wasn’t stand-alone. You had to first get the edmx from VS and only then, you could use my designer.

Moreover, this first version was only usable with EF v1 (EF4 wasn’t released when I developed it).

I decided to start a new version from scratch with a lot of great new features // You can submit me your ideas.

I find some points on my dev interesting and, because I’m always very interested by different opinions, I decided to share my technical choices in several posts.

The idea I will develop in this post is to have my EDM Designer as modular as possible in order to

  • be able to easily integrate a new EF version
  • be able to choose the version we want to use on runtime
  • be able to integrate non SQL Server DB
  • be able to change pluralize / singularize logic
  • etc.

For modular aspect, I use PRISM with Unity.

Unity is very useful for unit test. However, in my case, I want to demonstrate here that it’s also very useful for modular application development.

This is the solution explorer of this post illustration:

image_thumb[5]

I use PRISM in order to define EF available versions: EF v1 and EF 4 in my case.

For this, I define them into my App.config file:

<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
>


In my App class constructor, I call my Bootstrapper :



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



In my Bootstrapper, I use PRISM UnityBootstrapper in order to instantiate each module then create my Shell and then show it:



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;
    }
}



I use View First approach (my View instantiates my ViewModel). If we look at the code, we can think that it’s a ViewModel first but in fact it isn’t because I use Unity.



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



In my case, IShellViewModel is associated with ShellViewModel in my UnityContainer, so in my Shell instantiation, Unity instantiates a ShellViewModel to put it as Shell constructor parameter.



My ShellViewModel returns available modules in order to add them into the ListBox (for my demo sample).



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



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



How to get these modules?



I use the following code:



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

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



To be able to use it, I first have to register my modules in my unity container.



I use my Module constructor to do it:



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
; }
}



So now my two modules are added to my UnityContainer during their instantiations on the Bootstrapper which allows my ViewModel to find them.



 



The EDM structure (with 3 SSDL, CSDL and MSL parts) is the same for EF v1 and EF4.



So I don’t want to redefine EDM class for EF4. However, the CSDL is different (CSDL Functions were added for example). So, I want that my EDM class defined in EDM.Base instantiates EDM.v4.CSDL class when I use v4 Module and EDM.Base.CSDL class when I use EF v1.



How to do it?



Unity can help us.



Using my main UnityContainer, I create a child container for each module. In v4 module child container, I associate EDM.Base.CSDL with EDM.v4.CSDL. Then I add a property EDM which will be created by my child unity container and my EDM class will instantiate the CSDL class:


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;
        }
    }
}



We can verify it:


<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_thumb[4]



image_thumb[6]

This entry was posted in 15211, 15212, 15236, 7671. Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>