gpt4 book ai didi

c# - 自动生成一个强类型的 AppSettings 类

转载 作者:太空狗 更新时间:2023-10-29 22:56:10 25 4
gpt4 key购买 nike

首先是问题:

这可能吗?我的灵感来自 Joe Wrobel's work (被遗忘的 Codeplex project 的还原)。在这里,您为提供者创建您的配置文件,它为它创建强类型,有效地为 Profile 类创建外观。

现在是背景故事!

我真的不喜欢magic strings .它们非常糟糕,在更新您的应用程序时可能会导致一些严重的问题。使用过 PHP 和 ColdFusion 等语言后,我知道将它们放入您的应用程序并在需要更改它们之前忘记它们很容易。然后你必须找到它们的每一个变体并相应地改变它们。

如果您遵循“开箱即用”的应用程序模板,.NET 并没有那么好。许多示例使用 web.config 中的 appsettings 来存储各种设置。这确实是一个很好的存储位置,并且非常适合大多数应用程序。然而,当您开始直接调用它们时,问题就开始出现了——例如 ConfigurationManager.AppSettings["MyAppSetting"]。然后,当您重新使用魔术字符串时,您的生活实际上并不比 PHP 用户好多少。

这是facades的地方进来。Facades 提供了一种方法,可以在一个地方从一个神奇的字符串创建一个强类型的对象,并让开发人员从应用程序的其余部分引用它。

现在,我不再使用 web.config 来包含我的应用程序设置,而是使用数据库来保存它们。在应用程序启动时,名称/值组合被检索,然后通过 Set 按顺序添加到 ConfigurationManager.AppSettings。没什么大不了的(除了我之前的 problem!)。

我的数据层、服务层和表示层都可以访问这个“应用程序外观”,并保存诸如应用程序模式之类的东西,哪个服务端点使用 yada yada yada 并限制必须寻找许多魔术字符串的需要,向下到两个神奇的字符串 - 一个(名称)在外观中,另一个(名称和值)在创建点(对我来说是数据库)。

这个门面类最终会变得很大,我最终会厌倦必须更新它们。

所以我想做的是有一个 ApplicationFacade 类,它在每次构建完成时自动生成。现在回到起点……这可能吗?

最佳答案

您也可以为此目的使用 CodeSmith 模板。优点是您可以在模板文件属性中设置要在每次构建时重新生成(设置 BuildAction = "Complile")

已编辑我也在寻找这样的解决方案。谷歌搜索后,我找到了基本的 T4 模板来生成这样一个类。我重新设计了它,您可以在下面找到它。

模板正在从您的 Web.config/App.config 文件中为 appSetting 部分生成包装器类

假设您在配置文件中有以下几行设置

  <appSettings>
<add key="PageSize" value="20" />
<add key="CurrentTheme" value="MyFavouriteTheme" />
<add key="IsShowSomething" value="True" />
</appSettings>

处理模板后你会得到下面的类

namespace MyProject.Core
{
/// <remarks>
/// You can create partial class with the same name in another file to add custom properties
/// </remarks>
public static partial class SiteSettings
{
/// <summary>
/// Static constructor to initialize properties
/// </summary>
static SiteSettings()
{
var settings = System.Configuration.ConfigurationManager.AppSettings;
PageSize = Convert.ToInt32( settings["PageSize"] );
CurrentTheme = ( settings["CurrentTheme"] );
IsShowSomething = Convert.ToBoolean( settings["IsShowSomething"] );
}

/// <summary>
/// PageSize configuration value
/// </summary>
public static readonly int PageSize;

/// <summary>
/// CurrentTheme configuration value
/// </summary>
public static readonly string CurrentTheme;

/// <summary>
/// IsShowSomething configuration value
/// </summary>
public static readonly bool IsShowSomething;

}
}

将以下代码保存到 *.tt 文件 并包含到您要放置生成文件的项目中。在每个构建中重新生成类 see my answer here模板从值中识别字符串、日期时间、整数和 bool 类型

<#@ assembly name="System.Core" #>
<#@ assembly name="System.Xml" #>
<#@ assembly name="System.Xml.Linq" #>
<#@ import namespace="System" #>
<#@ import namespace="System.Text" #>
<#@ import namespace="System.IO" #>
<#@ import namespace="System.Linq" #>
<#@ import namespace="System.Xml.Linq" #>
<#@ import namespace="Microsoft.VisualBasic" #>
<#@ template language="VB" debug="True" hostspecific="True" #>
<#@ output extension=".Generated.cs" #>
<#
Dim projectNamespace as String = "MyProject.Core"
Dim className as String = "SiteSettings"
Dim fileName as String = "..\..\MyProject.Web\web.config"

Init(fileName)

#>
//------------------------------------------------------------------------------
// FileName = <#= path #>
// Generated at <#= Now.ToLocaltime() #>
//
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if
// the code is regenerated.
//
// NOTE: Please use the Add a Reference to System.Configuration assembly if
// you get compile errors with ConfigurationManager
// </auto-generated>
//------------------------------------------------------------------------------

using System;
using System.Configuration;

namespace <#= projectNamespace #>
{
/// <remarks>
/// You can create partial class with the same name in another file to add custom properties
/// </remarks>
public static partial class <#= className #>
{
/// <summary>
/// Static constructor to initialize properties
/// </summary>
static <#= className #>()
{
var settings = System.Configuration.ConfigurationManager.AppSettings;
<#= AddToCostructor(path) #> }

<#= RenderApplicationSettings(path) #> }
}

<#+
Dim path as String = ""
Dim doc as XDocument = Nothing

Public Sub Init(fileName as String)
Try
path = Host.ResolvePath(fileName)
If File.Exists(path) Then
doc = XDocument.Load(path)
End If
Catch
path = "<< App.config or Web.config not found within the project >>"
End Try
End Sub

Public Function AddToCostructor(ByVal path as String) as String
If doc Is Nothing Then Return ""

Dim sb as New StringBuilder()

For Each result as XElement in doc...<appSettings>.<add>
sb.Append(vbTab).Append(vbTab).Append(vbTab)
sb.AppendFormat("{0} = {1}( settings[""{0}""] );", result.@key, GetConverter(result.@value))
sb.AppendLine()
Next

Return sb.ToString()

End Function

Public Function RenderApplicationSettings(ByVal path as String) as String
If doc Is Nothing Then Return ""

Dim sb as New StringBuilder()

For Each result as XElement in doc...<appSettings>.<add>
dim key = result.@key
sb.Append(vbTab).Append(vbTab)
sb.Append("/// <summary>").AppendLine()
sb.Append(vbTab).Append(vbTab)
sb.AppendFormat("/// {0} configuration value", key).AppendLine()
sb.Append(vbTab).Append(vbTab)
sb.Append("/// </summary>").AppendLine()
sb.Append(vbTab).Append(vbTab)
sb.AppendFormat("public static readonly {0} {1}; ", GetPropertyType(result.@value), key)
sb.AppendLine().AppendLine()
Next

Return sb.ToString()

End Function

Public Shared Function GetConverter(ByVal prop as String) as String
If IsNumeric(prop) Then Return "Convert.ToInt32"
If IsDate(prop) Then Return "Convert.ToDateTime"
dim b as Boolean
If Boolean.TryParse(prop, b) Then Return "Convert.ToBoolean"
Return ""
End Function

Public Shared Function GetPropertyType(ByVal prop as String) as String
If IsNumeric(prop) Then Return "int"
If IsDate(prop) Then Return "DateTime"
dim b as Boolean
If Boolean.TryParse(prop, b) Then Return "bool"
Return "string"
End Function

#>

关于c# - 自动生成一个强类型的 AppSettings 类,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1583642/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com