Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/asp.net-mvc/14.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Asp.net mvc StructureMap IOC/DI和对象创建_Asp.net Mvc_Inversion Of Control_Structuremap - Fatal编程技术网

Asp.net mvc StructureMap IOC/DI和对象创建

Asp.net mvc StructureMap IOC/DI和对象创建,asp.net-mvc,inversion-of-control,structuremap,Asp.net Mvc,Inversion Of Control,Structuremap,我正在用asp.net mvc和Structuremap ioc/di构建小型web商店。我的Basket类使用会话对象进行持久化,我希望使用SM通过IBasket接口创建我的Basket对象。我的篮子实现需要构造函数中mvc的HttpSessionStateBase会话状态包装器,该包装器在控制器/操作中可用。如何为SM注册IBasket实现? 这是我的篮子界面: public interface IBasketService { BasketContent GetBasket(

我正在用asp.net mvc和Structuremap ioc/di构建小型web商店。我的Basket类使用会话对象进行持久化,我希望使用SM通过IBasket接口创建我的Basket对象。我的篮子实现需要构造函数中mvc的HttpSessionStateBase会话状态包装器,该包装器在控制器/操作中可用。如何为SM注册IBasket实现? 这是我的篮子界面:

public interface IBasketService    {
    BasketContent GetBasket();
    void AddItem(Product productItem);
    void RemoveItem(Guid guid);
}
和SM注册:

ForRequestedType(typeof (IBasketService)).TheDefaultIsConcreteType(typeof (StoreBasketService));
但我的StoreBasketService实现具有以下构造函数:

public StoreBasketService(HttpSessionStateBase sessionState)
如何向SM提供HttpSessionStateBase对象,该对象仅在controller中可用?
这是我第一次使用SM IOC/DI,在官方文档和网站中找不到解决方案/示例

如果您必须让StoreBasketService使用会话,我会尝试在HttpSessionState周围定义一个接口和包装器,而不是使用HttpSessionStateBase,以便您也可以使用StructureMap注册它。包装器将从当前上下文获取会话状态。向StructureMap注册包装器,然后让StoreBasketService将接口作为构造函数的参数。然后,结构映射应该知道如何创建接口包装器的实例并将其注入到StoreBasketService类中

使用接口和包装器将允许您在单元测试中模拟包装器,muc的模拟方式与HttpSessionStateBase允许模拟实际会话的方式相同

public interface IHttpSessionStateWrapper
{
    HttpSessionState GetSessionState();
}

public class HttpSessionStateWrapper : IHttpSessionStateWrapper
{
    public virtual HttpSessionState GetSessionState()
    {
       return HttpContext.Current.Session;
    }
}

ForRquestedType(typeof(IHttpSessionStateWrapper))
   .TheDefaultIsConcreteType(typeof(IHttpSessionStateWrapper));
但是,您可以让StructureMap在注册时使用.CacheByInstanceScope.HttpContext在会话中实际存储篮子。实际上,让StoreBasketService实现内部存储而不是在会话中存储可能会更好——这样,从类的角度来看,您就完全失去了对会话状态的依赖,解决方案也会更简单。您的内部存储可以是一个字典,因为这是您通过接口访问它们的方式

另见:


如果您必须让StoreBasketService使用会话,我会尝试在HttpSessionState周围定义一个接口和包装器,而不是使用HttpSessionStateBase,以便您也可以使用StructureMap注册它。包装器将从当前上下文获取会话状态。向StructureMap注册包装器,然后让StoreBasketService将接口作为构造函数的参数。然后,结构映射应该知道如何创建接口包装器的实例并将其注入到StoreBasketService类中

使用接口和包装器将允许您在单元测试中模拟包装器,muc的模拟方式与HttpSessionStateBase允许模拟实际会话的方式相同

public interface IHttpSessionStateWrapper
{
    HttpSessionState GetSessionState();
}

public class HttpSessionStateWrapper : IHttpSessionStateWrapper
{
    public virtual HttpSessionState GetSessionState()
    {
       return HttpContext.Current.Session;
    }
}

ForRquestedType(typeof(IHttpSessionStateWrapper))
   .TheDefaultIsConcreteType(typeof(IHttpSessionStateWrapper));
但是,您可以让StructureMap在注册时使用.CacheByInstanceScope.HttpContext在会话中实际存储篮子。实际上,让StoreBasketService实现内部存储而不是在会话中存储可能会更好——这样,从类的角度来看,您就完全失去了对会话状态的依赖,解决方案也会更简单。您的内部存储可以是一个字典,因为这是您通过接口访问它们的方式

另见:


我只是从StructureMap开始,没有得到您描述的结果。 我使用一个简单的类执行了一个简单的测试,将Structuremap配置为cacheby HttpContext,从我所看到的,cacheby.HttpContext意味着在相同的请求中,您将得到相同的实例。。。不在同一会话中

我的类的构造函数在私有字段中设置日期/时间 我有一个按钮,它以1秒的间隔获取MyClass的2个实例。。。 然后在标签中显示两个实例的时间

第一次按下此按钮时,对象A和B是相同的实例,因为它们的创建时间与预期完全相同

如果在会话中缓存实例,第二次单击该按钮,您可能会认为创建时间没有更改。。。然而,在我的测试中,我得到了一个新的创建时间

结构映射配置:


我只是从StructureMap开始,没有得到您描述的结果。 我使用一个简单的类执行了一个简单的测试,将Structuremap配置为cacheby HttpContext,从我所看到的,cacheby.HttpContext意味着在相同的请求中,您将得到相同的实例。。。不在同一会话中

我的类的构造函数在私有字段中设置日期/时间 我有一个按钮,它以1秒的间隔获取MyClass的2个实例。。。 然后在标签中显示两个实例的时间

第一次按下此按钮时,对象A和B是相同的实例,因为它们的创建时间与预期完全相同

如果在会话中缓存实例,第二次单击该按钮,您可能会认为创建时间没有更改。。。豪 在我的测试中,我得到了一个新的创建时间

结构映射配置:


您还可以使用ObjectFactory.Inject方法之一将HttpSessionStateBase注入StructureMap。然后,它将使用注入的HttpSessionStateBase调用构造函数。

您还可以使用ObjectFactory.Inject方法之一将HttpSessionStateBase注入StructureMap。然后,它将使用注入的HttpSessionStateBase调用构造函数。

我刚刚第一次尝试创建自定义范围。。。用它构建一个小型web应用程序,就我所见,它似乎可以工作。这将在当前用户会话中缓存对象,并且只要您仍在同一会话中,就会返回相同的对象:

public class HttpSessionBuilder : CacheInterceptor
{
    private readonly string _prefix = Guid.NewGuid().ToString();

    protected override CacheInterceptor clone()
    {
        return this;
    }

    private string getKey(string instanceKey, Type pluginType)
    {
        return string.Format("{0}:{1}:{2}", pluginType.AssemblyQualifiedName, instanceKey, this._prefix);
    }

    public static bool HasContext()
    {
        return (HttpContext.Current.Session != null);
    }

    protected override bool isCached(string instanceKey, Type pluginType)
    {
        return HttpContext.Current.Session[this.getKey(instanceKey, pluginType)] != null;
    }

    protected override object retrieveFromCache(string instanceKey, Type pluginType)
    {
        return HttpContext.Current.Session[this.getKey(instanceKey, pluginType)];
    }

    protected override void storeInCache(string instanceKey, Type pluginType, object instance)
    {
        HttpContext.Current.Session.Add(this.getKey(instanceKey, pluginType), instance);
    }

}
您必须在global.asax应用程序_start中配置ObjectFactory,如下所示

        ObjectFactory.Initialize(x=>
            x.ForRequestedType<MyClass>().InterceptConstructionWith(new HttpSessionBuilder()));

我刚刚第一次尝试创建自定义范围。。。用它构建一个小型web应用程序,就我所见,它似乎可以工作。这将在当前用户会话中缓存对象,并且只要您仍在同一会话中,就会返回相同的对象:

public class HttpSessionBuilder : CacheInterceptor
{
    private readonly string _prefix = Guid.NewGuid().ToString();

    protected override CacheInterceptor clone()
    {
        return this;
    }

    private string getKey(string instanceKey, Type pluginType)
    {
        return string.Format("{0}:{1}:{2}", pluginType.AssemblyQualifiedName, instanceKey, this._prefix);
    }

    public static bool HasContext()
    {
        return (HttpContext.Current.Session != null);
    }

    protected override bool isCached(string instanceKey, Type pluginType)
    {
        return HttpContext.Current.Session[this.getKey(instanceKey, pluginType)] != null;
    }

    protected override object retrieveFromCache(string instanceKey, Type pluginType)
    {
        return HttpContext.Current.Session[this.getKey(instanceKey, pluginType)];
    }

    protected override void storeInCache(string instanceKey, Type pluginType, object instance)
    {
        HttpContext.Current.Session.Add(this.getKey(instanceKey, pluginType), instance);
    }

}
您必须在global.asax应用程序_start中配置ObjectFactory,如下所示

        ObjectFactory.Initialize(x=>
            x.ForRequestedType<MyClass>().InterceptConstructionWith(new HttpSessionBuilder()));
???这样行吗


???那有用吗?

我今天就试试,thanx。但对于使用SM缓存Basket类,IS.Httpcontext将对象存储在Httpcontext.items字典中,该字典仅在一个页面请求中可用,但我希望它贯穿整个用户会话。今天我将尝试一下,thanx。但对于使用SM缓存Basket类,IS.Httpcontext将对象存储在Httpcontext.items字典中,该字典仅在一个页面请求中可用,但我希望它贯穿整个用户会话。
        ObjectFactory.Initialize(x=>
            x.ForRequestedType<MyClass>().InterceptConstructionWith(new HttpSessionBuilder()));
ForRequestedType<IBasketService>()
    .TheDefault.Is.OfConcreteType<StoreBasketService>()
    .WithCtorArg("sessionState").EqualTo(HttpContext.Current.Session);