نکته: آشنایی اولیه با مفاهیم MEF از ملزومات این بخش است.
»ابتدا یک Class Library به نام Views ایجاد نمایید و اینترفیس زیر را به صورت زیر در آن تعریف نمایید. این اینترفیس رابط بین کنترلر و View از طریق ViewModel خواهد بود.
public interface IBookView : IView { void Show(); void Close(); }
Install-Package WAF
<Window x:Class="Shell.BookShell" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="Book View" Height="350" Width="525"> <Grid> <DataGrid ItemsSource="{Binding Books}" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Width="400" Height="200"> <DataGrid.Columns> <DataGridTextColumn Header="Code" Binding="{Binding Code}" Width="100"></DataGridTextColumn> <DataGridTextColumn Header="Title" Binding="{Binding Title}" Width="300"></DataGridTextColumn> </DataGrid.Columns> </DataGrid> </Grid> </Window>
[Export(typeof(IBookView))] [PartCreationPolicy(CreationPolicy.NonShared)] public partial class BookShell : Window, IBookView { public BookShell() { InitializeComponent(); } }
»یک Class Library به نام Models بسازید و بعد از ایجاد آن، کلاس زیر را به عنوان مدل Book در آن کپی کنید:
public class Book { public int Code { get; set; } public string Title { get; set; } }
[Export] [Export(typeof(ViewModel<IBookView>))] public class BookViewModel : ViewModel<IBookView> { [ImportingConstructor] public BookViewModel(IBookView view) : base(view) { } public ObservableCollection<Book> Books { get; set; } }
به دلیل اینکه سازنده پیش فرض در این کلاس وجود ندارد حتما باید از ImportingConstructor استفاده نماییم تا CompositionContainer در هنگام عملیات وهله سازی Exception صادر نکند.
»بخش بعدی ساخت یک Class Library دیگر به نام Controllers است. در این Library نیز بعد از ارجاع به اسمبلیهای زیر کتابخانه WAF را نصب نمایید.
- Views
- Models
- ViewModels
- System.ComponentModel.Composition
[Export] public class BookController { [ImportingConstructor] public BookController(BookViewModel viewModel) { ViewModelCore = viewModel; } public BookViewModel ViewModelCore { get; private set; } public void Run() { var result = new List<Book>(); result.Add(new Book { Code = 1, Title = "Book1" }); result.Add(new Book { Code = 2, Title = "Book2" }); result.Add(new Book { Code = 3, Title = "Book3" }); ViewModelCore.Books = new ObservableCollection<Models.Book>(result); (ViewModelCore.View as IBookView).Show(); } }
طراحی Bootstrapper
در پروژههای ماژولار Bootstrapper از ملزومات جدانشدنی این گونه پروژه هاست. برای این کار ابتدا یک WPF Application دیگر به نام Bootstrapper ایجاد نماید. سپس ارجاعی به اسمبلیهای زیر را در آن قرار دهید:
»Controllers
»Views
»ViewModels
»Shell
»System.ComponentModel.Composition
»نصب بسته WAF با استفاده از nuget
حال یک کلاس به نام AppBootstrapper ایجاد نمایید و کدهای زیر را در آن کپی نمایید:
public class AppBootstrapper { public CompositionContainer Container { get; private set; } public AggregateCatalog Catalog { get; private set; } public void Run() { Catalog = new AggregateCatalog(); Catalog.Catalogs.Add(new AssemblyCatalog(Assembly.GetExecutingAssembly())); Catalog.Catalogs.Add(new AssemblyCatalog(String.Format("{0}\\{1}", Environment.CurrentDirectory, "Shell.dll"))); Catalog.Catalogs.Add(new AssemblyCatalog(String.Format("{0}\\{1}", Environment.CurrentDirectory, "ViewModels.dll"))); Catalog.Catalogs.Add(new AssemblyCatalog(String.Format("{0}\\{1}", Environment.CurrentDirectory, "Controllers.dll"))); Container = new CompositionContainer(Catalog); var batch = new CompositionBatch(); batch.AddExportedValue(Container); Container.Compose(batch); var bookController = Container.GetExportedValue<BookController>(); bookController.Run(); } }
نکته بخش Startup را از فایل App.Xaml خذف نمایید و در متد Startup این فایل کد زیر را کپی کنید:
public partial class App : Application { protected override void OnStartup(StartupEventArgs e) { new Bootstrapper.AppBootstrapper().Run(); } }
نکته: میتوان بخش اسکن اسمبلیها را توسط یک DirecotryCatalog به صورت زیر خلاصه کرد:
Catalog.Catalogs.Add(new DirectoryCatalog(Environment.CurrentDirectory));
نکته: میتوان به جای جداسازی فیزیکی لایهها آنها را از طریق Directoryها به صورت منطقی در قالب یک اسمبلی نیز مدیریت کرد.
نکته: بهتر است به جای رفرنس مستقیم اسمبلیها به Bootstrapper با استفاده از Pre post build در قسمت Build Event، اسمبلیهای مورد نظر را در یک مسیر Build کپی نمایید که روش آن به تفصیل در این پست و این پست شرح داده شده است.
دانلود سورس پروژه