使用Castle.Windsor使用类型化的工厂实例化SqlConnection时,我们遇到了一个奇怪的问题:
注册看起来像这样:
container.Register(Component.For<IDbConnectionFactory>().AsFactory().LifestyleTransient());
container.Register(Component.For<IDbConnection>().ImplementedBy<SqlConnection>()
.LifestyleTransient()
.DependsOn(Dependency.OnValue<string>
(ConfigurationManager.ConnectionStrings["DbConnectionString"].ConnectionString)));
和IDbConnectionFactory
:
public interface IDbConnectionFactory
{
IDbConnection Create();
void Release();
}
现在,当我尝试使用以下代码访问新连接时:
using (var connection = _connectionFactory.Create())
{
}
我有一个例外:
An unhandled exception of type
'Castle.MicroKernel.ComponentActivator.ComponentActivatorException' occurred
in Castle.Windsor.dll
Additional information: Error setting property SqlConnection.AccessToken in component
System.Data.SqlClient.SqlConnection. See inner exception for more information.
If you don't want Windsor to set this property you can do it by either decorating it
with DoNotWireAttribute or via registration API.
Alternatively consider making the setter non-public.
此异常的问题是SqlConnection
.NET 4.5.1的System.Data中的类型不包含该属性,AccessToken
而.NET 4.6的类型中包含该属性。换句话说,如果我尝试手动执行
var connection = new SqlConnection("connectionstring");
connection.AccessToken = "";
如果为.NET 4.5.1配置了项目,则会出现构建错误,但是如果为.NET 4.6配置了项目,则在设置AccessToken时会出现运行时错误。
知道为什么Castle.Windsor尝试创建v4.6 SqlConnection而不是.NET 4.5.1吗?
解决方法/问题
我可以通过告诉Castle忽略该属性来解决该问题,但这似乎是一种破解。为此,我需要将其添加到PropertiesIgnore
注册中:
container.Register(Component.For<IDbConnection>().ImplementedBy<SqlConnection>()
.PropertiesIgnore(info => info.Name.Equals("AccessToken"))
.LifestyleTransient()
.DependsOn(Dependency.OnValue<string>
(ConfigurationManager.ConnectionStrings["DbConnectionString"].ConnectionString)));
从4.5开始,所有.NET版本都已就位更新,您可以在此处看到。
这意味着,一旦安装了.NET 4.6,无论您如何实例化它,都将始终获得.NET 4.6版本的SqlConnection。
在Visual Studio中构建应用程序时,将针对特定版本的.NET Framework进行构建,该版本通常位于以下文件夹中:C:\ Program Files(x86)\ Reference Assemblies \ Microsoft \ Framework.NETFramework
这意味着在构建msbuild时可以检查您使用的不是目标框架版本中没有的功能。
但是,当您运行64位应用程序时,它将使用通常位于C:\ Windows \ Microsoft.NET \ Framework64 \ v4.0.30319中的程序集
对于从.NET 4.0到.NET 4.6的所有版本,这是同一文件夹,这就是就地升级的意思。
因此,当您在安装了.NET 4.6的开发环境上执行应用程序时,您将始终获得.NET 4.6版本(至少除非您执行特殊操作以加载程序集的其他版本)。
Castle Windsor将尝试使用公共设置器设置属性,并且它将使用反射来查找属性,这意味着即使您是根据4.5.1进行构建的,它也会在.NET 4.6机器上找到.NET 4.6属性。
尝试设置AccessToken时失败的原因很可能是因为您的连接字符串与设置AccessToken不兼容。
如果您检查AccessToken setter的源代码,即使尝试仅将AccessToken设置为空字符串,如果尝试为不兼容的连接字符串设置它,也会看到它将引发异常。
由于不需要将任何依赖项注入到SqlConnection对象中,因此还可以使用new运算符简单地创建它,然后避免因Windsors尝试注入连接属性而引起的问题。使用此注册应该可以:
container.Register(Component.For<IDbConnection>().ImplementedBy<SqlConnection>()
.LifestyleTransient()
.UsingFactoryMethod(() => new SqlConnection
(ConfigurationManager.ConnectionStrings["DbConnectionString"].ConnectionString)));
本文收集自互联网,转载请注明来源。
如有侵权,请联系[email protected] 删除。
我来说两句