در قسمت 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 رو با سلیقه خودتون ایجاد کنید و بعد پروژه رو اجرا و نتیجه رو مشاهده کنید.