gpt4 book ai didi

c# - 如何使用 Windsor 将依赖项注入(inject)自定义 RoleProvider?

转载 作者:行者123 更新时间:2023-11-30 17:49:25 26 4
gpt4 key购买 nike

我将 Windsor 与 ASP.NET MVC4 一起使用我写了一个自定义 RoleProvider围绕遗留安全框架。我需要将连接字符串和文件路径注入(inject)提供程序,以便我可以将它们提供给遗留框架,但是当我开始使用 AuthorizeAttribute 时,我意识到我不知道如何拦截提供者的构造以注入(inject)这些值。

如果包含代码有帮助,我的角色提供者有这种构造函数:

public class CustomRoleProvider : RoleProvider
{
public CustomRoleProvider(string connectionString, string logPath)
{
LegacySecurity.ConnectionString = connectionString;
LegacySecurity.LogPath = logPath;
}

[Method overrides go here...]
}

我的 AppSettingsConvention看起来像这样:

public class AppSettingsConvention : ISubDependencyResolver
{
public bool CanResolve(CreationContext context,
ISubDependencyResolver contextHandlerResolver,
ComponentModel model,
DependencyModel dependency)
{
return ConfigurationManager.AppSettings.AllKeys.Contains(dependency.DependencyKey)
&& TypeDescriptor.GetConverter(dependency.TargetType).CanConvertFrom(typeof (string));
}

public object Resolve(CreationContext context,
ISubDependencyResolver contextHandlerResolver,
ComponentModel model,
DependencyModel dependency)
{
return TypeDescriptor.GetConverter(dependency.TargetType)
.ConvertFrom(ConfigurationManager.AppSettings[dependency.DependencyKey]);
}
}

(最初来自这里:http://blog.ploeh.dk/2012/07/02/PrimitiveDependencies/)

我希望我能以某种方式替换其中一项服务,就像我替换 HttpControllerActivator 一样。在 ApiController 中使用依赖注入(inject)

这可能吗?或者我是否需要寻找另一种方式来提供这些依赖项?

最佳答案

我的研究结果:

  • Windsor (与 StructureMap 不同)没有将属性注入(inject)现有对象的方法
  • AuthorizeAttribute不直接调用 RoleProvider 实现,它调用 Thread.CurrentPrincipal返回 IPrincipal实现...
  • 基本上不可能提供已解决的 RoleProviderAuthorizeAttribute ,即使您可以通过编写自己的 IFilterProvider 实现在它调用提供程序之前捕获它(参见 IFilterProvider and separation of concerns)

我最终做的是在 CustomRoleProvider 上提供一个方法设置连接字符串和日志路径,然后在 Application_Start 中设置它:

protected void Application_Start()
{
AreaRegistration.RegisterAllAreas();
WebApiConfig.Register(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);

var provider = Roles.Provider as CustomRoleProvider;
if (provider != null) provider.Initialize(ConfigurationManager.AppSettings[ConnectionKey], ConfigurationManager.AppSettings[LogPathKey]);
GlobalConfiguration.Configuration.Services.Replace(typeof(IHttpControllerActivator), _container.Resolve<IHttpControllerActivator>());
ControllerBuilder.Current.SetControllerFactory(_container.Resolve<IControllerFactory>());
}

可能有更好的方法来做到这一点,但目前我采用了务实的解决方案。

更新 2014-02-12

我找到了另一种通过反射替换 Roles 类中的提供者的方法。您的 Web 配置文件中只需要 <roleManager enabled="true" />并覆盖 Name在你的CustomRoleProvider返回 "CustomRoleProvider"然后在 Application_Start方法添加这个:

if (!(Roles.Provider is CustomRoleProvider))
{
var rolesType = typeof (Roles);
var flags = BindingFlags.Static | BindingFlags.NonPublic;
var provider = _container.Resolve<CustomRoleProvider>();
rolesType.GetField("s_Provider", flags).SetValue(null, provider);
var providers = new RoleProviderCollection();
providers.Add(provider);
rolesType.GetField("s_Providers", flags).SetValue(null, providers);
}

调用Roles.Provider强制 Roles类来执行它的初始化魔法(否则我们必须设置大量其他私有(private)字段)并且我们需要替换集合,因为 Roles 类的消费者调用它来寻找合适的提供者。

但是,我不确定我是否一定会推荐这个,我不确定这是否完全足够,但到目前为止它似乎对我有用。

更新 2014-02-20

有一种不涉及魔法反射的不同方法 - http://bugsquash.blogspot.co.uk/2010/11/windsor-managed-membershipproviders.html

尽管这篇博文谈论的是 MembershipProvider , 更改 RoleProvider 的代码相当简单反而。本质上,这是使用一种适配器模式,将实际角色提供者的解析留给适配器。它确实涉及使容器静态化并以一种服务定位器的方式使用它,但我认为这是一个小的权衡。

关于c# - 如何使用 Windsor 将依赖项注入(inject)自定义 RoleProvider?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21682314/

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