0

如何使用 autofac 将IServiceManager属性注入此类?这是一个自定义资源提供程序工厂类,当您调用HttpContext.GetGlobalResourceObject("", "MyResource")以获取资源字符串时会调用它。

public class SqlResourceProviderFactory : ResourceProviderFactory
{
    // needs autofac property injection
    public IServiceManager ServiceManager { get; set; }

    public override IResourceProvider CreateGlobalResourceProvider(string classKey)
    {
        ...
    }

    public override IResourceProvider CreateLocalResourceProvider(string virtualPath)
    {
        ...
    }

    public static string GetAppRelativePath(string logicalPath)
    {
        ...
    }
}
4

1 回答 1

1

我遇到了同样的问题——使用 ASP.NET——ResourceProviderFactory不幸的是,答案是你必须使用 service location

任何可以注入任何东西或更改内置 ASP.NET 行为的管道都没有“挂钩”。因此,如果您需要将某些内容放入属性中,则必须在构造函数中进行设置。

public class SqlResourceProviderFactory : ResourceProviderFactory
{
  public IServiceManager ServiceManager { get; set; }

  public SqlResourceProviderFactory()
  {
    this.ServiceManager =
      DependencyResolver.Current.GetService<IServiceManager>();
  }
}

是的,真的很丑

这里需要考虑的非常重要的一点,尤其是关于 Autofac,是您IServiceManager注册的生命周期范围。

ResourceProviderFactory创建一次并被缓存。与来自 Create* 方法的全局/本地资源提供程序相同。我们在这方面玩得很开心,因为这意味着HttpContext在创建工厂时不一定有一个InstancePerHttpRequest.

  • 您的或生成的资源提供者使用的任何东西ResourceProviderFactory- 一直到堆栈 - 都应该注册SingleInstanceInstancePerDependency
  • 如果可能,直接引用应用程序容器,而不是使用DependencyResolver.Current(对于 Autofac,它需要一个 active )。HttpContext这意味着您需要在其他地方存储对它的引用(全局静态变量?)并使用它。

这是更完整的解决方案可能涉及的内容:

// Create some "holder" for the app container.
public static class ApplicationContainerProvider
{
  public static ILifetimeScope Container { get; set; }
}


// In Global.asax, build your container and set it in both
// the DependencyResolver AND in the holder class.
var builder = new ContainerBuilder();
builder.RegisterType<Something>().As<ISomething>();
var container = builder.Build();
var resolver = new AutofacDependencyResolver(container);
DependencyResolver.SetResolver(resolver);
ApplicationContainerProvider.Container = container;


// In your service location, reference the container instead of
// DependencyResolver.
public class SqlResourceProviderFactory : ResourceProviderFactory
{
  public IServiceManager ServiceManager { get; set; }

  public SqlResourceProviderFactory()
  {
    this.ServiceManager =
      ApplicationContainerProvider.Container.Resolve<IServiceManager>();
  }
}

请注意,由于您是从根容器中解决该问题的,因此它将在应用程序的整个生命周期内一直存在。即使您将其注册为InstancePerDependency,由于 .NET 的内部缓存,它也只会创建一次。

如果您不喜欢这样创建自己的静态持有者类,您可以使用CommonServiceLocatorAutofac.Extras.CommonServiceLocator包将其抽象出来。

于 2014-02-25T15:51:43.813 回答