首页 文章

Autofac WCF集成 - 根据请求数据解析依赖关系

提问于
浏览
3

如何配置Autofac容器,以便它根据operation-parameter(请求对象)的属性值解析WCF服务的依赖关系?

例如,鉴于此数据 Contract ......

[DataContract]
public class MyRequest
{
    [DataMember]
    public bool MyBool { get; set; }
}

这个WCF服务......

public class MyWcfService : IWcfService
{
    private IService m_service;

    public MyWcfService(IService service)
    {
        m_service = service;
    }

    public virtual MyResponse Operation(MyRequest request) { }
}

和这些依赖...

public interface IService { }
public class TypeA : IService { }
public class TypeB : IService { }

如果MyBool等于true,我希望容器解析TypeA,否则解决TypeB . 这个功能可用吗?我应该以不同方式解决问题吗?

约束:

  • 避免使用Autofac.Extras.Multitenant软件包 .

  • 还希望保持服务构造函数的签名不变 . (见下面的答案)

2 回答

  • 1

    有几种方法可以实现这一目标 . 其中一种方法是使用 IIndex<K,V> . 它's built-in 2574804 feature that chooses between service implementations based on a key. You can find more info on Autofac' s wiki page . 示例代码可能如下所示:

    // Register your dependency with a key, for example a bool flag
    builder.RegisterType<TypeA>().Keyed<IService>(true);
    builder.RegisterType<TypeB>().Keyed<IService>(false);
    
    // Your service could look like:
    public class MyWcfService
    {
        private readonly IIndex<bool, IService> _services;
    
        // Inject IIndex<Key,Value> into the constructor, Autofac will handle it automatically
        public MyWcfService(IIndex<bool, IService> services)
        {
            _services = services;
        }
    
        public virtual void Operation(MyRequest request)
        {
            // Get the service that you need by the key
            var service = _services[request.MyBool];
        }
    }
    

    另一种方法是使用元数据功能 . 有关wiki page的更多信息 .

  • 5

    Option 1 - Using Autofac:

    创建服务实例的Autofac实例提供程序不使用或传递Autofac中的latest implementation of the method操作latest implementation of the method . 请注意 message 参数未使用 .

    public class AutofacInstanceProvider : IInstanceProvider
    {
        // lots of code removed...
    
        public object GetInstance(InstanceContext instanceContext, Message message)
        {
            if (instanceContext == null)
            {
                throw new ArgumentNullException("instanceContext");
            }
            var extension = new AutofacInstanceContext(_rootLifetimeScope);
            instanceContext.Extensions.Add(extension);
            return extension.Resolve(_serviceData);
        }
    }
    

    So to get the behavior you want with existing Autofac code, you'll need to inject the dependency into your class using something other than constructor injection ,这是@Alexandr Nikitin's solution . 这是合理的,但我同意评论"not loving it" .

    Option 2 - A Custom IInstanceProvider:

    编写自定义WCF IInstanceProvider是一个合理的选择,但它将是很多代码 .

    好消息是code in Autoface.Integration.WCF是一个很好的例子,你可以将你的实现插入到Autofac中 .

    坏消息是Autofac.Integration.WCF代码本身不使用依赖注入 . 例如 AutofacDependencyInjectionServiceBehavior 直接调用 var instanceProvider = new AutofacInstanceProvider(_rootLifetimeScope, _serviceData) . 因此,您必须实现 AutofacInstanceProviderAutofacDependencyInjectionServiceBehaviorAutofacHostFactory 的替代品,甚至更多 . 然后,您需要为 AutofacInstanceContext 创建一个扩展名,以包含从消息中读取的信息 . 它的代码很多 .

    如果您打算使用自定义IInstanceProvider,我建议您阅读Carlos Figueira的博客:

    • WCF可扩展性 - IInstanceProvider - 为了良好的背景

    • WCF可扩展性 - Message Inspectors - 搜索以WCF开头的部分消息对象只能“消耗一次” . 检查消息时,您需要遵循这些规则 .

相关问题