MVC 克隆控制器上下文

MVC Cloning Controller Context

我在实现 ControllerContext 的可克隆版本时遇到了一些问题。我需要这个,因为我试图缓存它并稍后在我的系统中无法访问此信息的部分访问它,我无法将它作为参数传递。这是我取得的成就:

public class ControllerContextClonable : ControllerContext, ICloneable
{
    public object Clone()
    {
        var cloneContext = (ControllerContext)MemberwiseClone();

        return cloneContext;
    }

    public static List<ControllerContextClonable> ToList( ControllerContextClonable context )
    {
        return new List<ControllerContextClonable>{ context };
    }
}

问题是:当我缓存它时,我有 ControllerContext 但我需要向我的缓存方法传递一个 ControllerContextClonable 对象。如何将我的 ControllerContext 转换为 ControllerContextClonable ?这就是我试图传递它和缓存方法的方式:

//If i try to call my method with the safe convertion i get a null object
CacheMethods.SetContextCache( context as ControllerContextClonable );

public static void SetContextCache( ControllerContextClonable context, string cacheKey = "SiteContext" )
{
    CacheList<ControllerContextClonable>.RemoveCache( cacheKey );
    CacheList<ControllerContextClonable>.Add( new List<ControllerContextClonable> { context } );
    CacheList<ControllerContextClonable>.CacheIt( cacheKey );
}

public static ControllerContextClonable GetCachedContext( string cacheKey = "SiteContext" )
{
    CacheList<ControllerContextClonable>.LoadCached( cacheKey );

    if( CacheList<ControllerContextClonable>.LoadCached( cacheKey ) )
    {
        return CacheList<ControllerContextClonable>.DataList.FirstOrDefault();
    }

    return null;
}

我如何正确地将正在执行的 ControllerContext 转换为我的 ControllerContextClonable class 以便在缓存中使用?另外,如果我做错了,谁能告诉我正确的方法?

编辑:

我将解释我的解决方法:我正在创建一个模板解析系统,它将使用标签系统解析模板,在此标签中,用户将提供 ViewModel class 和他希望使用的模板 View

有了这个,我将使用 代码来实例化此 ViewModel。这段代码不允许我将 controllercontext 作为参数传递,我试图修改它以接受该参数,但它会给我一个 Common language runtime detected an invalid program 错误。

现在的问题是,在这种情况下,我有一个 ViewModel 需要使用我的 Filter 获取保存在 ViewBag 上的信息。我能想到的唯一解决方案是缓存上下文并访问它,但我在转换部分失败了。我可以用其他方式解决这个问题吗?我需要的是在我的 ViewModel 构造函数调用的某些方法中访问 Context

这是ViewModel:

public class LanguageTestViewModel
{
    //Properties

    public LanguageTestViewModel() { Initialize( "", "", 0 ); }

    public LanguageTestViewModel( string where, string order, int take ) { Initialize( where, order, take ); }

    private void Initialize( string where, string order, int take )
    {
        var Context = CacheMethods.GetCachedContext();
        var EList   = HelperMethods.CreateSelectListItem( "SELECT A STATE", Context );
        var States  = CacheMethods.GetStatesForm( Context );

        //Do stuff
    }
}

编辑 2

我必须更改我的存储方法,因为我正在使用 HttpRuntime.Cache,这是一个共享存储,我无法存储上下文信息,它可以根据用户、设备、位置等而改变。 . 说我需要这个信息放在一个 per-user 存储上。有什么想法吗?

我有一个解决方案给你。克隆控制器实例,然后您就可以访问 objects.Notice 我正在使用实现 IControllerContextClonableHomeController。这个例子是最简单的解决方案。但它有效。例如

using System.Collections.Generic;
using System.Web.Mvc;

namespace WebApplication1.Controllers
{
    public class HomeController : Controller, IControllerContextClonable
    {
        public ActionResult Index()
        {
            var controller = (HomeController) this.MemberwiseClone();
            var list = ToList(controller);

            return View();
        }

        public List<IControllerContextClonable> ToList(IControllerContextClonable context)
        {

            return new List<IControllerContextClonable> { context};
        }
    }    

    public interface IControllerContextClonable
    {
        List<IControllerContextClonable> ToList(IControllerContextClonable context);    
    }
}

输出。 ControllerContext 实例水合得很好。

SetContextCache 方法将具有如下签名。注意参数类型是 IControllerContextClonable。这样 SetContextCache 方法将接受任何实现 IControllerContextClonable

的类型
public static void SetContextCache(IControllerContextClonable context, string cacheKey = "SiteContext" )
{
    CacheList<IControllerContextClonable>.RemoveCache( cacheKey );
    CacheList<IControllerContextClonable>.Add( new List<IControllerContextClonable> { context} );
    CacheList<IControllerContextClonable>.CacheIt( cacheKey );
}

然后您可以传递实现 IControllerContextClonable 的类型(class)的任何实例,因为 below.This 是有效的,因为 HomeController 实现了 IControllerContextClonable。您可以访问该对象,并且可以根据需要对其进行操作。

例如

  var homeController = new HomeController();

  CacheMethods.SetContextCache(homeController);