سؤال

أقوم بإنشاء متجر ويب صغير باستخدام asp.net mvc وStructuremap ioc/di.تستخدم فئة السلة الخاصة بي كائن الجلسة للاستمرار، وأريد استخدام SM لإنشاء كائن السلة الخاص بي من خلال واجهة IBasket.يحتاج تنفيذ سلتي إلى HttpSessionStateBase (مجمّع حالة الجلسة من mvc) في المُنشئ، والذي يتوفر داخل وحدة التحكم/الإجراء.كيف يمكنني تسجيل تطبيق IBasket الخاص بي لـ SM؟
هذه هي واجهة السلة الخاصة بي:

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)

كيف أقوم بتوفير كائن HttpSessionStateBase إلى SM، وهو متوفر فقط في وحدة التحكم؟
هذا هو أول استخدام لي لـ SM IOC/DI، ولا يمكنني العثور على الحل/المثال في الوثائق الرسمية وموقع الويب؛)

هل كانت مفيدة؟

المحلول

إذا كان لديك على الاطلاق أن يكون StoreBasketService الخاص بك استخدام الدورة، كنت تميل إلى تحديد واجهة والتفاف حول HttpSessionState بدلا من استخدام HttpSessionStateBase بحيث يمكنك تسجيله مع StructureMap كما well.The المجمع سيحصل على حالة جلسة العمل من السياق الحالي. تسجيل المجمع مع 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));

public class StoreBasketService
{
   HttpSessionState session;
   public StoreBasketService( IHttpSessionstateWrapper wrapper )
   {
      session = wrapper.GetSessionState();
   }

   // basket implementation ...
}

ولكن، هل يمكن أن يكون StructureMap تخزين الواقع سلتك في الدورة باستخدام .CacheBy(InstanceScope.HttpContext) عند تسجيله. قد يكون فعلا من الأفضل أن يكون لديك StoreBasketService تنفيذ تخزين داخلية بدلا من تخزين الأشياء في الدورة - ثم تفقد الاعتماد على حالة جلسة العمل تماما (من وجهة نظر صفك) والحل يمكن أن يكون أكثر بساطة. التخزين الداخلية الخاصة بك يمكن أن يكون Dictionary<Guid,Product> لأن هذا هو كيف الوصول إليها عن طريق واجهة الخاص بك.

وانظر أيضا:

HTTP: / /www.lostechies.com/blogs/chad_myers/archive/2008/07/15/structuremap-basic-scenario-usage.aspx

HTTP : //www.lostechies.com/blogs/chad_myers/archive/2008/07/17/structuremap-medium-level-usage-scenarios.aspx

نصائح أخرى

ForRequestedType<IBasketService>()
    .TheDefault.Is.OfConcreteType<StoreBasketService>()
    .WithCtorArg("sessionState").EqualTo(HttpContext.Current.Session);

و؟؟ هل هذا العمل؟

لقد بدأت للتو باستخدام StructureMap، ولم أحصل على النتائج التي تصفها.لقد أجريت اختبارًا بسيطًا باستخدام فئة بسيطة، وقمت بتكوين Structuremap على ذاكرة التخزين المؤقت بواسطة HttpContext، ومن ما أستطيع رؤيته، يعني CacheBy.HttpContext ضمن نفس الطلب أنك ستحصل على نفس المثيل...وليس في نفس الجلسة

مُنشئ صفي ، يحدد التاريخ/الوقت في حقل خاص لدي زر يحصل على مثيلتين من myClass مع فاصل واحد ثانية ...ثم يعرض وقت كلتا الحالتين في التسمية.

عند الضغط على هذا الزر لأول مرة، يصبح الكائنان A وB نفس المثال، حيث أن وقت إنشائهما هو نفسه تمامًا، كما هو متوقع.

بالنقر فوق الزر مرة ثانية، تتوقع ألا يتغير وقت الإنشاء إذا تم تخزين المثيلات مؤقتًا في الجلسة...ومع ذلك، في اختباري أحصل على وقت إنشاء جديد ...

تكوين الخريطة الهيكلية:

         ObjectFactory.Initialize(x=>x.ForRequestedType<MyClass>(). CacheBy(InstanceScope.HttpContext));

حدث النقر على الزر لصفحة الاختبار

     protected void btnTest_Click(object sender, EventArgs e)
    {
        MyClass c = ObjectFactory.GetInstance<MyClass>();
        System.Threading.Thread.Sleep(1000);
        MyClass b = ObjectFactory.GetInstance<MyClass>();



        lblResult.Text = String.Format("cache by httpcontext First:{0}  Second:{1}  session id {2} ", c.GetTimeCreated(), b.GetTimeCreated(),Session.SessionID);
    }

صفي

public class MyClass
{
    private DateTime _timeCreated;
    public MyClass()
    {
        _timeCreated = DateTime.Now;
    }

    public string GetTimeCreated()
    {
        return _timeCreated.ToString("dd/MM/yyyy hh:mm:ss");
    }
}

ويمكنك أيضا استخدام إحدى الطرق ObjectFactory.Inject لحقن HttpSessionStateBase إلى StructureMap. ثم فإنه استدعاء المنشئ مع حقن HttpSessionStateBase.

ولقد قدمت أول محاولة لي في خلق نطاق مخصص ... إنشاء تطبيق ويب صغيرة مع ذلك، وبقدر ما أستطيع أن أرى، على ما يبدو للعمل. وهذا التخزين المؤقت الكائن داخل الدورة الحالية للمستخدم وسوف يعود نفس الكائن طالما كنت البقاء داخل نفس الدورة:

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);
    }

}

لديك لتكوين ObjectFactory على النحو التالي في global.asax Application_start

        ObjectFactory.Initialize(x=>
            x.ForRequestedType<MyClass>().InterceptConstructionWith(new HttpSessionBuilder()));
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top