在执行过程中动态覆盖WebConfigurationManager.AppSettings["SomeProp

本文关键字:quot SomeProp AppSettings WebConfigurationManager 执行 过程中 动态 覆盖 | 更新日期: 2023-09-27 18:12:37

我有一个这样的代码:

// can't make any changes at that class
class MyClass
{
    void SomeMethod()
    {
        // some code ...
        var someVar = WebConfigurationManager.AppSettings["SomeProperty"];
        // some code ...
    }
}

我不能改变代码,但我需要那个WebConfigurationManager。AppSettings["SomeProperty"]根据一些外部条件(例如,根据用户角色)返回不同的值。我在寻找某种方法重写对那个属性的访问。在那个重写方法中,我会检查用户角色和返回合适的值

有办法吗?

我发现这个问题:是否有一种方法来覆盖ConfigurationManager.AppSettings?但它似乎不适合我,因为这里的WebConfigurationManager值。AppSettings["SomeProperty"]在应用程序启动时设置一次。我需要动态地做

在执行过程中动态覆盖WebConfigurationManager.AppSettings["SomeProp

在MVC中,为了简化测试和模拟,我倾向于对通过接口引用的所有公共类(如Request, Session和ConfigManager)使用自定义对象。显然,你基本上不需要从头开始实现类,所以你的实现可以是一个包装器,它实际上是在底层使用。net类,但它也提供了在中间插入一些自定义逻辑的机会,就像你的情况一样。

因此,你可以创建webconfigurationManager的包装器,使用GetAppConfig(key)这样的方法包含你自己的逻辑。使用依赖注入的概念就很容易了,只要你需要,就可以使用这个类。

因此,举一个简单的例子:

//this will be injected
public MyControllerCtor(IConfig cfg)
public interface IConfig
{
   string GetAppConfig(string key);
}
public class myConfig:IConfig
{
   public string GetAppConfig(string key)
   {    
      //your logic
      var someVar = WebConfigurationManager.AppSettings["SomeProperty"];
      //your logic
      return yourCustomAppSetting;
   }
}

这种方法的一大优点是,如果你想将你的配置存储在数据库或服务中,并且改变你的代码,你只需要改变你的接口实现并注入新的实例。

如果你不能改变读取AppSettings的代码,那么就没有办法做你想做的事情。WebConfigurationManager不能从外部插入或替换。

你必须修改代码

不,当然不是。

如果你不能改变类,那么你也不能改变行为。微软为什么要在WebApplicationManager中放置一个"覆盖"功能,这是没有一般理由的。通常,人们希望能够改变自己的类,或者正确地设计它,以便能够以正确的方式覆盖它。

这听起来像你需要做一些逻辑从web.config检索值后。如果逻辑修改了值本身,您可以始终在web中存储格式字符串。配置。

下面是使用连接字符串设置的示例。我在运行时使用格式字符串填充服务器名称:

<add name="sqlconnection" connectionString="Server={0}'SQLEXPRESS;Database=xxx;Trusted_Connection=True;"/>    

然后我使用这个逻辑:

string connect = ConfigurationManager.ConnectionStrings["sqlconnection"].ConnectionString;
if (!String.IsNullOrEmpty(connect))
{
    //check to see if the connection string needs to be set at runtime
    if (connect.Contains("{0}"))
        connect = String.Format(connect, HttpContext.Current.Server.MachineName);
}
return connect;

EDIT:如果你不能直接编辑类,我会考虑创建一个部分类来实现这个

如果您直接更改Web。配置它们将只在下一次请求时有效,据我所知,这不是期望的效果。

你不能直接影响WebConfigurationManager。AppSettings["SomeProperty"],这是期望的行为,因为AppSettings作为配置是静态的。

为了达到接近你想要的效果,我建议你使用HttpContext.Current.Items集合,如果满足条件,你将在Application_BeginRequest中初始化为一定的值,或者默认为WebConfigurationManager。否则AppSettings("SomeProperty")。
那么,不要访问WebConfigurationManager。AppSettings["SomeProperty"]你将访问HttpContext.Current.Items["SomeProperty"].