C# 在ASP.NET中遵循DRY原则

C# 在ASP.NET中遵循DRY原则,c#,asp.net,dry,C#,Asp.net,Dry,我最近刚刚参与了一个经典的ASP.NET项目,其中包含大量存储和读取会话和查询字符串中的值。这可能类似于以下内容: Session["someKey"]=someValue; 在代码的其他地方,会话中的值被读取。显然,这违反了DRY原则,因为文字字符串键将分布在整个代码中。避免这种情况的一种方法是将所有键存储为常量,在需要读写会话的任何地方都可以引用这些常量。但我不确定这是最好的方法。你会建议我如何最好地处理这个问题,这样我就不会违反干燥原则了 我觉得你读得太多了。我更多地关注可以封装在函数中

我最近刚刚参与了一个经典的ASP.NET项目,其中包含大量存储和读取会话和查询字符串中的值。这可能类似于以下内容:

Session["someKey"]=someValue;

在代码的其他地方,会话中的值被读取。显然,这违反了DRY原则,因为文字字符串键将分布在整个代码中。避免这种情况的一种方法是将所有键存储为常量,在需要读写会话的任何地方都可以引用这些常量。但我不确定这是最好的方法。你会建议我如何最好地处理这个问题,这样我就不会违反干燥原则了

我觉得你读得太多了。我更多地关注可以封装在函数中的东西。也就是说,不要到处重复相同的五行代码,而是将这五行代码封装在一个函数中,并在需要的地方调用该函数


例如,您只需在字典(本例中为会话对象)中设置一个值,这是在字典中存储和检索对象的最简单方法。

创建一个单独的公共类,您可以在其中定义常量,例如

public class SessionVars
{
   public const string SOME_KEY = "someKey";
   public const string SOME_OTHER_KEY = "someOtherKey";
}
然后,您可以在代码中的任何位置访问如下会话变量:

Session[SessionVars.SOME_KEY]=someValue;

通过这种方式,您可以获得IntelliSence和其他功能。

您还可以选择将对该会话对象的访问权放在一个基本页中,并将其包装在一个属性中:

class BasePage : Page
{
   ...
   public string MySessionObject
   {
      get
      {
         if(Session["myKey"] == null)
            return string.Empty;
         return Session["myKey"].ToString();
      }
      set
      {
          Session["myKey"] = value;
      }
   }
   ...
}

这里重复的是
myKey
字符串,但它被封装到属性中。如果您想避免这种情况,请使用键创建一个常量并替换字符串。

我一辈子都记不起这段代码是从哪里来的,但它非常好:

using System;
using System.Web;

namespace Project.Web.UI.Domain
{
    public abstract class SessionBase<T> where T : class, new()
    {
        private static readonly Object _padlock = new Object();

        private static string Key
        {
            get { return typeof(SessionBase<T>).FullName; }
        }

        public static T Current
        {
            get
            {
                var instance = HttpContext.Current.Session[Key] as T;

                lock (SessionBase<T>._padlock)
                {
                    if (instance == null)
                    {
                        HttpContext.Current.Session[Key] 
                          = instance 
                          = new T();
                    }
                }
                return instance;
            }
        }

        public static void Clear()
        {
            var instance = HttpContext.Current.Session[Key] as T;
            if (instance != null)
            {
                lock (SessionBase<T>._padlock)
                {
                    HttpContext.Current.Session[Key] = null;
                }
            }
        }
    }
}
然后沿着这条路扩展
MyClass
,您不需要记住所有的键值,将它们存储在AppSettings或静态类中的Const变量中。您只需定义要存储的内容:

public class MyClassSession : SessionBase<MyClass>
{ 
}

+1这是我倾向于遵循的模式-它确实有助于消除那些讨厌的打字错误。在这种情况下,你不应该使用
const
<代码>静态只读更合适(也更安全)。这如何减轻“不要重复”的原则?您仍然在到处编写相同的1行程序,您只是在使用常量变量而不是键的实例字符串?这与我之前所做的类似,可能是我将要做的,结合在属性中包装会话。它消除了记住字符串并正确键入的需要,您获得了intellisense,并且只有一个地方可以更改密钥。至于这不符合干燥原则的问题,至少这是向前迈出的一步。如果你认为编写一行SessionVars.SOME_KEY违反了DRY,那么我认为这是对DRY的一种解读,正如在另一篇文章中所回答的那样。我希望你永远不要继承一个充满需要维护的神奇字符串的项目……感谢@Erik Philips提供了结构良好的代码。我真的很喜欢。“能给我们举个更清楚的例子吗?@JohnNate我不知道怎么才能更清楚。”。是的,我想看一个在ASP.NET Web中应用代码的例子Forms@JohnNateAFAIK它可以在webforms中工作,无需修改。创建您的
MyClass
以存储结构化数据,从
SessionBase
派生您自己的
MyClassSession
类,然后在Web表单中使用
MyClassSession
public class MyClassSession : SessionBase<MyClass>
{ 
}
// Any Asp.Net method (webforms or mvc)
public void SetValueMethod()
{
  MyClassSesssion.Current.Blah1 = "asdf";
}

public string GetValueMethod()
{
  return MyClassSession.Current.Blah1;
}