我正在C# .NET Framework4.6中构建一个类库,它整合和简化了对各种后端数据源的数据访问。这些数据源是Azure表、Azure Blobs、Redis、DocumentDB数据和外部REST。所有这些数据都被多个系统在不同的平台上使用。在这一点上,我们有一个巨大的混乱的不同的系统,所有需要单独维护,每次一个后端数据源的变化,甚至轻微。更改表意味着我们需要在5-7码基之间更新代码。
问题是这个类库将从ASP.NET 2& 4、ASP.NET Core1.0和Windows应用程序中使用。它也有可能在其他环境中使用。
挑战在于,每个位置都需要一种方法来设置它们自己的配置字符串和访问键。我希望这只是配置文件的一部分,您可以添加您的信息。库将读取密钥并准备就绪,就像许多库所做的那样。
我的问题是,似乎没有通用的方式访问这些平台上的设置。我不希望为每个可以使用的平台创建一个自定义设置访问器。
有人能给我一个简单易用的解决方案吗?理想情况下,它不需要太多的外部依赖。
作为一个附带的问题,对于这些不同的系统,我预期还有什么其他的问题吗?
发布于 2016-03-06 02:48:52
如果它只是一个需要连接字符串的类,那么将连接字符串放在类的构造函数中。该类不应该直接从web.config或其他任何地方获取字符串。
如下所示:
public class ReadsSomethingFromSql
{
private readonly string _connectionString;
public ReadsSomethingFromSql(string connectionString)
{
_connectionString = connectionString;
}
public void InsertSomethingIntoSql()
{
using (var connection = new SqlConnection(_connectionString))
{
//Do something with connection string
}
}
}
这样,这个类就不负责阅读web.config的内容了。这可能会让人感到困惑,因为使用该类的人现在可能知道类期望连接字符串在web.config中。通过将其放入构造函数中,类显然需要一个连接字符串。
如果不使用依赖项注入,则调用方法可以这样做:
var reader = new ReadsSomethingFromSql(
ConfigurationManager.ConnectionStrings["myConnection"].ConnectionString);
但这只会把问题移开。如果要在自己的库中创建类实例,那么仍然存在相同的问题--您的库是直接从web.config读取的。
更好的解决方案是使用依赖注入来指定类所依赖的所有值。)在这篇文章中,这是一个很重要的话题。下面是一个使用Castle的依赖注入的起始示例。
使用它,您可以指定连接字符串的来源,如下所示:
container.Register(
Component.For<ReadsSomethingFromSql>()
.DependsOn(Dependency.OnValue("connectionString",
ConfigurationManager.ConnectionStrings["myConnection"].ConnectionString))
);
如果它不仅仅是一个连接字符串,可能是类需要的许多设置,那么您可以创建一个接口,如下所示:
public interface ISettings
{
string Setting1 { get; }
int SomeOtherSetting { get; }
}
并将其放入类的构造函数中,就像上面的连接字符串一样。
public class MyClass
{
private readonly ISettings settings;
public MyClass(ISettings settings)
{
_settings = settings;
}
这样,类就会引用_settings
,它是ISettings
的一个实例,但它并不“知道”实现是什么。
然后,您可以创建一个实现ISettings
的类,它从配置中获取值,如下所示:
public class Settings : ISettings
{
public string Setting1 { get { return ConfigurationManager.AppSettings["MyClass:Setting1"]; } }
public int SomeOtherSetting {
get
{
return Int32.Parse(ConfigurationManager.AppSettings["MyClass:SomeOtherSettings"]);
}
} }
}
这将解决您的类的问题取决于配置。它不依赖于配置。这将取决于ISettings
。
使用温莎,您的应用程序会像这样配置它:
container.Register(Component.For<ISettings,Settings>());
我并不是真的用这些粗略的例子来做依赖注入正义。但我用同样的问题开始了同样的道路。依赖注入是解决问题的方法,并且在许多其他方面也会使您受益。
更新:您提到的不需要修改类的使用者的。我想我看到了问题的一部分-你的Core1.0应用程序不会有web.config。
你可以妥协。修改类的构造函数并使参数成为可选参数。这样,在编写新的消费者时,可以使用依赖项注入。老消费者可以像现在这样工作,像这样:
public class ReadsSomethingFromSql
{
private readonly string _connectionString;
public ReadsSomethingFromSql(string connectionString = null)
{
_connectionString = connectionString
?? ConfigurationManager.ConnectionStrings["MyConnectionString"].ConnectionString;
}
发布于 2016-03-05 23:42:07
我不完全确定你想要什么:
1)库配置数据需要位于主项目的配置文件中? 2)库需要将所有其他项目的配置数据嵌入到自己的配置中?
如果#1,如果您需要什么,那么它就像使用您的配置文件一样容易。我目前正在生产,使用4个库的4个the应用程序,其中2个在使用它的项目上有自定义配置。我使用appSettings webconfig部分。库将使用以下方法读取该配置文件:
ConfigurationManager.AppSettings["<CONFIG KEY HERE>"]
如果是#2,那么它或多或少是一样的。只需为库的所有内容编写自定义配置,然后与所有数据一起发布即可。但我会做第一名的。
如果我把你的问题搞错了,那就对不起!如果你能更详细地解释你的情况,我会很乐意帮你的。
作为一个附带的问题,对于这些不同的系统,我预期还有什么其他的问题吗?
这是坏的,坏的,坏的!我只是有个相关的问题。查看我的帖子:Windows通用应用程序适合我吗?- UI迁移
拥有框架2和4将给您带来问题,同时也会混合平台和最新的microsoft技术,比如aspnet核心和UWA。
我会检查两次并做一些广泛的测试,然后在任何时候编写一些不起作用的代码。
干杯
https://stackoverflow.com/questions/35821065
复制相似问题