اندازهی قلم متن
تخمین مدت زمان مطالعهی مطلب:
چهار دقیقه
در پست قبلی با تکنولوژی MEF آشنا شدید.در این پست قصد دارم روش استفاده از MEF رو در Asp.Net MVC نمایش بدم. برای شروع یک پروژه پروژه MVC ایجاد کنید.
در قسمت Model کلاس Book رو ایجاد کنید و کدهای زیر رو در اون قرار بدید.
یک فولدر به نام Repositories ایجاد کنید و یک اینترفیس به نام IBookRepository رو به صورت زیر ایجاد کنید.
حالا نوبت به کلاس BookRepository میرسه که باید به صورت زیر ایجاد بشه.
بر روی پوشه کنترلر کلیک راست کرده و یک کنترلر به نام BookController ایجاد کنید و کدهای زیر رو در اون کپی کنید.
PartCreationPolicyکه شامل 3 نوع میباشد.
اگر با مفاهیمی نظیر CompositionContainer آشنایی ندارید میتونید پست قبلی رو مطالعه کنید.
حالا قصد داریم یک DependencyResolver رو با استفاده از MEF به صورت زیر ایجاد کنیم.(DependencyResolver برای ایجاد نمونه ای از کلاس مورد نظر برای کلاس هایی است که به یکدیگر نیاز دارند و برای ارتباط بین آن از Depedency Injection استفاده شده است.
حال یک کلاس Plugin ایجاد میکنیم.
همانطور که در این کلاس میبینید ابتدا یک CompositionContainer ایجاد کردیم که یک ComposablePartCatalog از نوع DirectoryCatalog به اون پاس دادم.
DirectoryCatalog یک مسیر رو دریافت کرده و Assemblyهای موجود در مسیر مورد نظر رو به عنوان Catalog در Container اضافه میکنه. میتونستید از یک AssemblyCatalog هم به صورت زیر استفاده کنید.
در تکه کد زیر ControllerFactory پروژه رو از نوع MEFControllerFactory قرار دادیم.
و در تکه کد زیر هم DependencyResolver پروژه از نوع MefDependencyResolver قرار دادیم.
کافیست در فایل Global نیز تغییرات زیر را اعمال کنیم.
در انتها View متناظر با BookController رو با سلیقه خودتون ایجاد کنید و بعد پروژه رو اجرا و نتیجه رو مشاهده کنید.
در قسمت Model کلاس Book رو ایجاد کنید و کدهای زیر رو در اون قرار بدید.
public class Book { public int Id { get; set; } public string Title { get; set; } public string ISBN { get; set; } }
یک فولدر به نام Repositories ایجاد کنید و یک اینترفیس به نام IBookRepository رو به صورت زیر ایجاد کنید.
public interface IBookRepository { IList<Book> GetBooks(); }
حالا نوبت به کلاس BookRepository میرسه که باید به صورت زیر ایجاد بشه.
[Export( typeof( IBookRepository ) )] public class BookRepository { public IList<Book> GetBooks() { List<Book> listOfBooks = new List<Book>( 3 ); listOfBooks.AddRange( new Book[] { new Book(){Id=1 , Title="Book1"}, new Book(){Id=2 , Title="Book2"}, new Book(){Id=3 , Title="Book3"}, } ); return listOfBooks; } }
بر روی پوشه کنترلر کلیک راست کرده و یک کنترلر به نام BookController ایجاد کنید و کدهای زیر رو در اون کپی کنید.
[Export] [PartCreationPolicy( CreationPolicy.NonShared )] public class BookController : Controller { [Import( typeof( IBookRepository ) )] BookRepository bookRepository; public BookController() { } public ActionResult Index() { return View( this.bookRepository.GetBooks() ); } }
- Shared: بعنی در نهایت فقط یک نمونه از این کلاس در هز Container وجود دارد.
- NonShared : یعنی به ازای هر درخواستی که از نمونهی Export شده میشود یک نمونه جدید ساخته میشود.
- Any : هر 2 حالت فوق Support میشود.
public class MEFControllerFactory : DefaultControllerFactory
{
private readonly CompositionContainer _compositionContainer;
public MEFControllerFactory( CompositionContainer compositionContainer )
{
_compositionContainer = compositionContainer;
}
protected override IController GetControllerInstance( RequestContext requestContext, Type controllerType )
{
var export = _compositionContainer.GetExports( controllerType, null, null ).SingleOrDefault();
IController result;
if ( export != null )
{
result = export.Value as IController;
}
else
{
result = base.GetControllerInstance( requestContext, controllerType );
_compositionContainer.ComposeParts( result );
}
}
}
حالا قصد داریم یک DependencyResolver رو با استفاده از MEF به صورت زیر ایجاد کنیم.(DependencyResolver برای ایجاد نمونه ای از کلاس مورد نظر برای کلاس هایی است که به یکدیگر نیاز دارند و برای ارتباط بین آن از Depedency Injection استفاده شده است.
public class MefDependencyResolver : IDependencyResolver { private readonly CompositionContainer _container; public MefDependencyResolver( CompositionContainer container ) { _container = container; } public IDependencyScope BeginScope() { return this; } public object GetService( Type serviceType ) { var export = _container.GetExports( serviceType, null, null ).SingleOrDefault(); return null != export ? export.Value : null; } public IEnumerable<object> GetServices( Type serviceType ) { var exports = _container.GetExports( serviceType, null, null ); var createdObjects = new List<object>(); if ( exports.Any() ) { foreach ( var export in exports ) { createdObjects.Add( export.Value ); } } return createdObjects; } public void Dispose() { } }
حال یک کلاس Plugin ایجاد میکنیم.
public class Plugin { public void Setup() { var container = new CompositionContainer( new DirectoryCatalog( HostingEnvironment.MapPath( "~/bin" ) ) ); CompositionBatch batch = new CompositionBatch(); batch.AddPart( this ); ControllerBuilder.Current.SetControllerFactory( new MEFControllerFactory( container ) ); System.Web.Http.GlobalConfiguration.Configuration.DependencyResolver = new MefDependencyResolver( container ); container.Compose( batch ); } }
DirectoryCatalog یک مسیر رو دریافت کرده و Assemblyهای موجود در مسیر مورد نظر رو به عنوان Catalog در Container اضافه میکنه. میتونستید از یک AssemblyCatalog هم به صورت زیر استفاده کنید.
var container = new CompositionContainer( new AssemblyCatalog( Assembly.GetExecutingAssembly() ) );
ControllerBuilder.Current.SetControllerFactory( new MEFControllerFactory( container ) );
System.Web.Http.GlobalConfiguration.Configuration.DependencyResolver = new MefDependencyResolver( container );
protected void Application_Start() { Plugin myPlugin = new Plugin(); myPlugin.Setup(); AreaRegistration.RegisterAllAreas(); RegisterRoutes( RouteTable.Routes ); } public static void RegisterRoutes( RouteCollection routes ) { routes.IgnoreRoute( "{resource}.axd/{*pathInfo}" ); routes.MapRoute( "Default", // Route name "{controller}/{action}/{id}", // URL with parameters new { controller = "Book", action = "Index", id = UrlParameter.Optional } // Parameter defaults ); }
در انتها View متناظر با BookController رو با سلیقه خودتون ایجاد کنید و بعد پروژه رو اجرا و نتیجه رو مشاهده کنید.