[英]Autofac WCF Integration - Resolve dependencies based on request data
How can I configure an Autofac container so it resolves the dependencies of a WCF service based on properties values of the operation-parameter (request object)? 如何配置Autofac容器,以便它根据operation-parameter(请求对象)的属性值解析WCF服务的依赖关系?
For example, given this data contract... 例如,鉴于此数据合同......
[DataContract]
public class MyRequest
{
[DataMember]
public bool MyBool { get; set; }
}
this WCF service... 这个WCF服务......
public class MyWcfService : IWcfService
{
private IService m_service;
public MyWcfService(IService service)
{
m_service = service;
}
public virtual MyResponse Operation(MyRequest request) { }
}
and these dependencies... 和这些依赖...
public interface IService { }
public class TypeA : IService { }
public class TypeB : IService { }
I would like the container to resolve TypeA if MyBool equals true and TypeB otherwise. 如果MyBool等于true,我希望容器解析TypeA,否则解决TypeB。 Is that feature available?
这个功能可用吗? Should I approach the problem differently?
我应该以不同方式解决问题吗?
Constraints: 约束:
There are a few ways to achieve this. 有几种方法可以实现这一目标。 One of the ways is to use
IIndex<K,V>
. 其中一种方法是使用
IIndex<K,V>
。 It's built-in "lookup" feature that chooses between service implementations based on a key. 它是内置的“查找”功能,可在基于密钥的服务实现之间进行选择。 You can find more info on Autofac's wiki page .
您可以在Autofac的维基页面上找到更多信息。 An example code could look like:
示例代码可能如下所示:
// 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];
}
}
Another approach is to use Metadata feature. 另一种方法是使用元数据功能。 More information on wiki page .
有关wiki页面的更多信息。
Option 1 - Using Autofac: 选项1 - 使用Autofac:
The Autofac instance provider that creates your service instance does not use or pass along the operation's message. 创建服务实例的Autofac实例提供程序不使用或传递操作的消息。 Here's the latest implementation of the method in Autofac.
这是Autofac 中该方法的最新实现 。 Notice the
message
parameter is unused. 请注意,
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 , which is @Alexandr Nikitin's solution . 因此,要使用现有的Autofac代码获得所需的行为,您需要使用构造函数注入之外的其他内容将依赖项注入到类中 ,这是@Alexandr Nikitin的解决方案 。 This is reasonable, but I agree with the comment "not loving it".
这是合理的,但我同意“不爱它”的评论。
Option 2 - A Custom IInstanceProvider: 选项2 - 自定义IInstanceProvider:
Writing a custom WCF IInstanceProvider is a reasonable option, but it will be a lot of code. 编写自定义WCF IInstanceProvider是一个合理的选择,但它将是很多代码。
The good news is that the code in Autoface.Integration.WCF is a nice example and you could plug your implementation into Autofac. 好消息是Autoface.Integration.WCF中的代码是一个很好的例子,你可以将你的实现插入到Autofac中。
The bad news is that Autofac.Integration.WCF code doesn't itself use dependency injection. 坏消息是Autofac.Integration.WCF代码本身不使用依赖注入。 For example
AutofacDependencyInjectionServiceBehavior
directly calls var instanceProvider = new AutofacInstanceProvider(_rootLifetimeScope, _serviceData)
. 例如,
AutofacDependencyInjectionServiceBehavior
直接调用var instanceProvider = new AutofacInstanceProvider(_rootLifetimeScope, _serviceData)
。 As a result you'll you have to implement a replacement for AutofacInstanceProvider
, AutofacDependencyInjectionServiceBehavior
, AutofacHostFactory
, and probably more. 因此,您必须实现
AutofacInstanceProvider
, AutofacDependencyInjectionServiceBehavior
, AutofacHostFactory
以及更多内容的替换。 Then you'll need to create an extension for the AutofacInstanceContext
to contain the information read from the message. 然后,您需要为
AutofacInstanceContext
创建一个扩展,以包含从消息中读取的信息。 Its a lot of code. 它的代码很多。
If you are going to do the custom IInstanceProvider I suggest reading up on Carlos Figueira's blog: 如果您打算使用自定义IInstanceProvider,我建议您阅读Carlos Figueira的博客:
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.