信息系统开发平台OpenExpressApp - 从compositewpf到MEF

  在信息系统开发平台OpenExpressApp - 发布for .Net4版本中介绍过现在从以前的compositewpf改为.Net4自带的MEF来作为扩展应用机制,MEF的主要架构可以通过之前写的.Net4下的MEF(Managed Extensibility Framework) 架构简介来简单了解一下,对于compositewpf不了解的可以去参考它的官方网站。本篇我将介绍一下OpenExpressApp升级到for .Net4版本时如何从从compositewpf更改到MEF,想了解MEF的简单应用的也可以看看。

compositewpf的应用

  compositewpf在OpenExpressApp for .Net3的应用主要有模块装载以及界面组合两个应用,下面分别介绍一下这两方面之前如何实现的,后面会介绍这两部分如何在MEF下实现。

模块加载

  •    在【OpenExpressApp.Host.WPF】项目的【Bootstrapper.cs】单元中通过重载GetModuleCatalog来获取模块目录
  
    
protected override IModuleCatalog GetModuleCatalog()
{
ModuleCatalog catalog
= new ModuleCatalog();
// 制定装载OpenExpressApp模块
catalog.AddModule( typeof (ExpressAppModule));

// 从目录装载
Directory.CreateDirectory( @" .\Module " );
var dirCatalog
= new DirectoryModuleCatalog() { ModulePath = @".\Module" };
dirCatalog.Initialize();
foreach (var module in dirCatalog.Modules)
{
catalog.AddModule(module);
}
// 等业务模块加载完毕在加载OpenExpressApp.Module.WPF模块。否则提前创建的DefaultOpen模块没有按钮。
catalog.AddModule( typeof (WPFModule));
return catalog;
}
  • 具体模块从IModule继承下来,并实现Initialize方法
  
    
public abstract class XXXModule :   Microsoft.Practices.Composite.Modularity. IModule
{
#region IModule Members
  public virtual void Initialize()
{ ......
}


UI组合

  • 【OpenExpressApp.Host.WPF】中的【DockableContentRegionAdapter.cs】和【DockableRegionAdapter.cs】增加两个Region适配器
  • 在Shell.xaml中注册Region:

   
     
< AvalonDock:DockingManager x:Name = " _dockingManager " >
< AvalonDock:ResizingPanel >
< AvalonDock:DockablePane AvalonDock:ResizingPanel.ResizeWidth = " 228 " >
< AvalonDock:DockableContent cal:RegionManager.RegionName ="Tools" Title = " 模块列表 " />
</ AvalonDock:DockablePane >
< AvalonDock:ResizingPanel Orientation = " Vertical " >
< AvalonDock:DocumentPane cal:RegionManager.RegionName="Workspace" />
< AvalonDock:DockablePane cal:RegionManager.RegionName="Pads" />
</ AvalonDock:ResizingPanel >
</ AvalonDock:ResizingPanel >
</ AvalonDock:DockingManager >

  • 在【OpenExpressApp.Module.WPF】项目的【WPFModule.cs】单元的初始化函数中增加控件到相应的Region
  
    
  this ._regionManager.RegisterViewWithRegion(ShellRegionNames.Tools, typeof (ModuleListPad));
  • 在【Application.cs】中的打开模块中把生成的模块显示在指定工作区域
  
    
public static object OpenModule(Type boType)
{
var regions
= GetRegions();
IRegion moduleRegion
= regions[ShellRegionNames.Tools];
IRegion mainRegion
= regions[ShellRegionNames.Workspace];
var modulePad
= moduleRegion.ActiveViews.First() as ModuleListPad;
BusinessObjectInfo selectItem
= GetModule(boType, modulePad);
Debug.Assert(selectItem
!= null , " 未找到这个模块,不能打开! " );
// 左边的控件
modulePad.lbModule.SelectedItem = selectItem;

// 右边的控件
object view = CreateView(mainRegion, selectItem);

// 日志
AuditLogService.LogAsync( new AuditLogItem()
{
Title
= " 打开模块: " + selectItem.Label,
ModuleName
= selectItem.Label,
Type
= AuditLogType.OpenModule
});

return view;
}
        private static object CreateView(IRegion mainRegion, BusinessObjectInfo selectItem)
        {
            object view = null;

             //如果已经打开则激活模块,否则新增模块窗体
            if (OpenModules.TryGetValue(selectItem.BOType, out view) == false)
            {
                if (selectItem.ModuleUIType != null)
                {
                    view = Activator.CreateInstance(selectItem.ModuleUIType);
                }
                else
                {
                    view = CreateModuleForm(selectItem);
                }


              mainRegion.Add(view); //添加到区域

                OpenModules.Add(selectItem.BOType, view);
            }


            mainRegion.Activate(view);


            return view;
        }

MEF的应用

  1. 从compositewpf转移到MEF,首先去除以前项目对Microsoft.Practices.XXX等项目的引用,加入对【System.ComponentModel.Composition】的引用来试用MEF
  2. 由于不用UI组合功能,删除【DockableContentRegionAdapter.cs】、【DockableRegionAdapter.cs】、【Bootstrapper.cs】
  3. 修改【App.xaml.cs】,不了解MEF基础的可以去网上搜索一下资料来学习一下
        
          
      private bool Compose()
    {
    var catalog
    = new AggregateCatalog();
    //添加模块程序集目录
      catalog.Catalogs.Add(
    new AssemblyCatalog(Assembly.GetExecutingAssembly()));
    catalog.Catalogs.Add(
    new AssemblyCatalog(
    Assembly.GetAssembly(
    typeof (OpenExpressApp.Module.ExpressAppModule))));
    catalog.Catalogs.Add(
    new AssemblyCatalog(
    Assembly.GetAssembly(
    typeof (OpenExpressApp.Module.WPF.SystemModule.WPFModule))));
    if (Directory.Exists( @" .\Module " )) catalog.Catalogs.Add( new DirectoryCatalog( @" .\Module " ));
    _container
    = new CompositionContainer(catalog);
    _container.ComposeExportedValue
    < CompositionContainer > (_container);
    //执行模块的初始化,注意:这里的IModule接口是在OpenExpressApp.Library中实现的
    var modules
    = _container.GetExportedValues < IModule > ();
    foreach (var module in modules)
    {
    module.Initialize();
    }

    CompositionBatch batch
    = new CompositionBatch();
    batch.AddPart(
    this );
    _container.Compose(batch);

    return
    true ;
    }

    在App()中启动

        
          
        if (Compose())
    {
    // Application.Current.Run(_container.GetExportedValue<Window>("OpenExpressApp.MainWindow"));
    _container.GetExportedValue <Window> ( " OpenExpressApp.MainWindow " ).Show();
    }
  4. 删除【Shell.xaml】中的Region设定,在【Shell.xaml.cs】中Export一些需要扩展的UI
        
          
    [Export(ContractName.MainWindow, typeof(Window))]
    public partial class Shell : Window, IPartImportsSatisfiedNotification
    {

    [Export(ContractName.Pads,
    typeof (ItemsControl))]
    public ItemsControl Pads
    {
    get
    {
    return Pads;
    }
    }

    [Export(ContractName.Workspace,
    typeof (IWorkspace))]
    private DocumentPaneWorkSpace _Workspace
    {
    get
    {
    return new DocumentPaneWorkSpace(workspace);
    }
    }
  5. 在【Shell.xaml.cs】中Import工具面板
        
          
    public partial class Shell : Window, IPartImportsSatisfiedNotification
    {
    [ImportMany(ContractName.Tools)]
    public IEnumerable < Control > Tools { get ; set ; }

    public void OnImportsSatisfied() //实现 IPartImportsSatisfiedNotification, 组合完毕后执行
    {
    foreach (var item in Tools)
    this .tools.Items.Add( new DockableContent() { Content = item });
    }
  6. 打开模块
    在【WPFModule】中Import组合容器CompositionContainer并赋值给OpenApplication.CompositionContainer
        
          
    [Export( typeof (IModule))]
    public class WPFModule : AdaptCommandModule
    {
    [Import]
    private CompositionContainer _compositionContainer = null ;

    /// <summary>
    /// 把ModuleListPad.xaml加入到region中。
    ///
    /// 加入ComboDataGrid.xaml到Resource中
    /// </summary>
    public override void Initialize()
    {
    base .Initialize();

    OpenApplication.CompositionContainer
    = _compositionContainer;

    在【OpenExpressApp.Module.WPF】的【Application.cs】中的【OpenApplication】类增加区域属性
        
          
    public static IWorkspace Workspace
    {
    get
    {
    return CompositionContainer.GetExportedValue <IWorkspace> (ContractName.Workspace);
    }
    }

    public static Control ModuleListPad
    {
    get
    {
    return CompositionContainer.GetExportedValue <Control> (ContractName.ModuleListPad);
    }
    }


    public static ItemsControl Pads
    {
    get
    {
    return CompositionContainer.GetExportedValue <ItemsControl> (ContractName.Pads);
    }
    }

    public static Selector ModuleListBox
    {
    get
    {
    return CompositionContainer.GetExportedValue <Selector> (ContractName.ModuleListBox);
    }
    }

  以上是迁移的主要修改部分,具体细节请大家去下载代码 信息系统开发平台OpenExpressApp - 发布for .Net4版本

 

更多内容: 开源信息系统开发平台之OpenExpressApp框架.pdf

 

欢迎转载,转载请注明:转载自周金根 [ http://zhoujg.cnblogs.com/ ]

    [Export(ContractName.MainWindow, typeof(Window))]
    public partial class Shell : Window, IPartImportsSatisfiedNotification
    {

你可能感兴趣的:(express)