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

时间:2014-01-20 20:52:32

标签: c# wcf autofac

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

例如,鉴于此数据合同......

[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 个答案:

答案 0 :(得分:5)

有几种方法可以实现这一目标。其中一种方法是使用IIndex<K,V>。它是内置的“查找”功能,可在基于密钥的服务实现之间进行选择。您可以在Autofac的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的更多信息。

答案 1 :(得分:1)

选项1 - 使用Autofac:

创建服务实例的Autofac实例提供程序不使用或传递操作的消息。这是Autofac中的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);
    }
}

因此,要使用现有的Autofac代码获得所需的行为,您需要使用构造函数注入以外的其他内容(例如@Alexandr Nikitin's solution)将依赖项注入到类中。这是合理的,但我同意“不爱它”的评论。

选项2 - 自定义IInstanceProvider:

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

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

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

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

  1. WCF可扩展性 - IInstanceProvider - 为了良好的背景
  2. WCF可扩展性 - Message Inspectors - 搜索以WCF开头的部分消息对象只能“消耗一次”。检查消息时,您需要遵循这些规则。