SORU
9 Ocak 2014, PERŞEMBE


MVC 4 ile MEF ya da 5 Takılabilir Mimarisi (2014)

Orchard CMS gibi bir takılabilir mimarisi ile MVC4/MVC5 bir uygulama oluşturmak için çalışıyorum. Projenin başlangıç ve auth, navigasyon vb ilgilenecek olan bir MVC uygulama var. Sonra ASP.NET sınıf kitaplıkları gibi birden çok modül ayrı olarak inşa edilecek ya da soyunmuş mvc projeleri ve denetleyicileri, görünümler, veri repo vb var.

Web ve indirme örnekler vb eğitimler geçiyor bütün gün geçirdim ve Kenny - http://kennytordeur.blogspot.in/2012/08/mef-in-aspnet-mvc-4-and-webapi.html en iyi örnek olduğunu buldu

Eğer bu DLL referans eklerseniz modülleri(ayrı DLL) denetleyicileri almak mümkün duyuyorum. Ama MEF kullanarak arkasındaki nedeni zamanında modülleri eklemek için güçlü olmak. Projenin başlangıç ~/// Modülleri bir dizine kopyalanması manzarası ile birlikte Silmek istiyorum (bunu başardım) ve MEF sadece onları almak. Mücadele MEF yük bu kütüphaneler yapmak.

Bu cevap anlatıldığı gibi de MefContrib denemek üzereyim bir sonraki şey ASP.NET MVC 4.0 Controllers and MEF, how to bring these two together?. Ama MEF bakmıyor MVC ile kutunun dışında çalışmak şaşırdım.

Benzer bir mimari çalışma (veya MefContrib olmadan) var mı? Ya bak ben olabilecek herhangi bir mevcut çerçeve biliyor musunuz? Başlangıçta ben bile Orchard CMS sıyırma ve bir çerçeve olarak kullanmayı düşündüm ama çok karmaşık. Ayrıca MVC5 uygulaması geliştirmek için iyi olurdu WebAPİ2 yararlanmak için.

CEVAP
10 Ocak 2014, Cuma


Tarif ettiğin gibi benzer bir takılabilir mimarisi olan bir proje üzerinde çalıştım ve aynı teknolojileri ASP.NET MVC MEF kullandı. Kimlik denetimi ele MVC uygulama, yetkilendirme ve tüm istekleri ASP.NET bir ev sahibi vardı. Eklentiler(modüller) alt klasör kopyalandı. Eklentileri de kendi modelleri, kontrolörler, manzaralı, css ve js dosyaları vardı 7 ** uygulamalar yapıldı. Bu da iş yapmak için takip ettiğimiz adımlar şunlardır:

MEF kurma

Uygulama başlangıçta bütün birleştirilebilir parçalar saptadığı motor MEF göre yarattık ve birleştirilebilir parçaların bir katalog oluşturur. Bu yalnızca bir kez uygulama başlangıç pefromed bir iştir. Motor bizim durumumuzda da Modules(Plugins) klasöründeki host bin klasöründe uygulama ya da bulunan tüm plugable parçaları, keşfetmek ister.

public class Bootstrapper
{
    private static CompositionContainer CompositionContainer;
    private static bool IsLoaded = false;

    public static void Compose(List<string> pluginFolders)
    {
        if (IsLoaded) return;

        var catalog = new AggregateCatalog();

        catalog.Catalogs.Add(new DirectoryCatalog(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "bin")));

        foreach (var plugin in pluginFolders)
        {
            var directoryCatalog = new DirectoryCatalog(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Modules", plugin));
            catalog.Catalogs.Add(directoryCatalog);

        }
        CompositionContainer = new CompositionContainer(catalog);

        CompositionContainer.ComposeParts();
        IsLoaded = true;
    }

    public static T GetInstance<T>(string contractName = null)
    {
        var type = default(T);
        if (CompositionContainer == null) return type;

        if (!string.IsNullOrWhiteSpace(contractName))
            type = CompositionContainer.GetExportedValue<T>(contractName);
        else
            type = CompositionContainer.GetExportedValue<T>();

        return type;
    }
}

Bu tüm MEF bölümleri keşfi gerçekleştiren sınıf örnek kodu. Sınıf Compose yöntemi Global.asax.cs dosyasında Application_Start yöntemi denir. Kod basitlik için azalır.

public class MvcApplication : System.Web.HttpApplication
{
    protected void Application_Start()
    {
        var pluginFolders = new List<string>();

        var plugins = Directory.GetDirectories(Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Modules")).ToList();

        plugins.ForEach(s =>
        {
            var di = new DirectoryInfo(s);
            pluginFolders.Add(di.Name);
        });

        AreaRegistration.RegisterAllAreas();
        RouteConfig.RegisterRoutes(RouteTable.Routes);
        Bootstrapper.Compose(pluginFolders);
        ControllerBuilder.Current.SetControllerFactory(new CustomControllerFactory());
        ViewEngines.Engines.Add(new CustomViewEngine(pluginFolders));
    }
}

Tüm eklentileri alt-klasör ana bilgisayar uygulamasının kök dizininde bulunan Modules klasör ayrı kopyalanır varsayılmıştır. Her eklenti klasörü Views alt klasör ve her eklenti dll içerir. Ayrıca özel denetleyicisi fabrika ve aşağıda tarif etmem olacak özel bir görünüm motoru başlatılır yukarıda Application_Start yöntemi.

MEF okur denetleyicisi fabrika oluşturma

İsteği işlemek için gereken denetleyicisi keşfedeceksiniz ki: burada özel kumanda fabrika tanımlama kodu

public class CustomControllerFactory : IControllerFactory
{
    private readonly DefaultControllerFactory _defaultControllerFactory;

    public CustomControllerFactory()
    {
        _defaultControllerFactory = new DefaultControllerFactory();
    }

    public IController CreateController(RequestContext requestContext, string controllerName)
    {
        var controller = Bootstrapper.GetInstance<IController>(controllerName);

        if (controller == null)
            throw new Exception("Controller not found!");

        return controller;
    }

    public SessionStateBehavior GetControllerSessionBehavior(RequestContext requestContext, string controllerName)
    {
        return SessionStateBehavior.Default;
    }

    public void ReleaseController(IController controller)
    {
        var disposableController = controller as IDisposable;

        if (disposableController != null)
        {
            disposableController.Dispose();
        }
    }
}

Ayrıca her denetleyici Export öznitelik ile işaretlenmiş olmalıdır:

[Export("Plugin1", typeof(IController))]
[PartCreationPolicy(CreationPolicy.NonShared)]
public class Plugin1Controller : Controller
{
    //
    // GET: /Plugin1/
    public ActionResult Index()
    {
        return View();
    }
}

Export öznitelik oluşturucu ilk parametre sözleşme adını belirtir ve eşsiz her Denetleyici olarak tanımlar çünkü benzersiz olmalıdır. PartCreationPolicy kontrolörleri, birden çok kişi için yeniden kullanılamaz çünkü Paylaşılmayan için ayarlanmış olması gerekir.

Görünüm Altyapısı oluşturma eklentileri manzarası bulmak için bilir

Özel görünüm altyapısı oluşturulması kongre tarafından görünüm motoru ana uygulama Views klasör sadece görünüm görünüyor, çünkü gereklidir. Eklentileri Modules ayrı klasörde olduğu için, Görünüm motoru oraya bakmayı anlatmaya da ihtiyacımız var.

public class CustomViewEngine : RazorViewEngine
{
    private List<string> _plugins = new List<string>();

    public CustomViewEngine(List<string> pluginFolders)
    {
        _plugins = pluginFolders;

        ViewLocationFormats = GetViewLocations();
        MasterLocationFormats = GetMasterLocations();
        PartialViewLocationFormats = GetViewLocations();
    }

    public string[] GetViewLocations()
    {
        var views = new List<string>();
        views.Add("~/Views/{1}/{0}.cshtml");

        _plugins.ForEach(plugin =>
            views.Add("~/Modules/"   plugin   "/Views/{1}/{0}.cshtml")
        );
        return views.ToArray();
    }

    public string[] GetMasterLocations()
    {
        var masterPages = new List<string>();

        masterPages.Add("~/Views/Shared/{0}.cshtml");

        _plugins.ForEach(plugin =>
            masterPages.Add("~/Modules/"   plugin   "/Views/Shared/{0}.cshtml")
        );

        return masterPages.ToArray();
    }
}

Eklentileri türü kesin belirlenmiş görünümleri ile sorunu çözmek

Sadece yukarıdaki kodu kullanarak, modelleri bin klasörün dışında var çünkü eklentiler(modüller) türü kesin belirlenmiş görünümleri kullanma, bulamadık. Bu sorunu çözmek için izleyin aşağıdaki link.

Bunu Paylaş:
  • Google+
  • E-Posta
Etiketler:

YORUMLAR

SPONSOR VİDEO

Rastgele Yazarlar

  • Darren Kitchen

    Darren Kitch

    3 EKİM 2011
  • MovieZoneET

    MovieZoneET

    22 Aralık 2009
  • MultiPlayStationMan

    MultiPlaySta

    17 Aralık 2009