我有一个看似相对常见的情况。我需要注入一个需要构造函数的依赖项。
我有一个如下所示的存储库:
public class ApprovalRepository : IApprovalRepository
{
private readonly MongoCollection<Approval> _collection;
public ApprovalRepository(MongoDatabase database)
{
this._collection = database.GetCollection<Approval>("Approvals");
}
// ...
}
端点配置如下所示:
public class EndpointConfig : IConfigureThisEndpoint,
AsA_Server, IWantCustomInitialization
{
public void Init()
{
NServiceBus.Configure.With().DefaultBuilder().JsonSerializer();
}
}
一个看起来像这样的处理程序:
public class PlaceApprovalHandler : IHandleMessages<PlaceApproval>
{
public IApprovalRepository ApprovalRepository { get; set; }
public void Handle(PlaceApproval message)
{
//
ApprovalRepository.Save(
new Approval
{
Id = message.Id,
Message = message.MessageText,
ProcessedOn = DateTime.UtcNow
});
}
}
然后我有一个类来进行自定义初始化:
public class ConfigureDependencies : IWantCustomInitialization
{
public void Init()
{
// configure Mongo
var client = new MongoClient("mongodb://localhost:27017/?safe=true");
var server = client.GetServer();
var database = server.GetDatabase("ServiceBusTest");
Configure.Instance.Configurer.RegisterSingleton<IApprovalRepository>(new ApprovalRepository(database));
}
}
结果是错误:
2013-04-11 17:01:03,945 [Worker.13] WARN NServiceBus.Unicast.UnicastBus [(null)] <(null)> - PlaceApprovalHandler failed handling message.
Autofac.Core.DependencyResolutionException: Circular component dependency detected: Server.PlaceApprovalHandler -> Server.ApprovalRepository -> Server.ApprovalRepository.
at Autofac.Core.Resolving.CircularDependencyDetector.CheckForCircularDependency(IComponentRegistration registration, Stack`1 activationStack, Int32 callDepth) in :line 0
at Autofac.Core.Resolving.ResolveOperation.GetOrCreateInstance(ISharingLifetimeScope currentOperationScope, IComponentRegistration registration, IEnumerable`1 parameters) in :line 0
我对Autofac并不熟悉。我也试过以下,也有类似的结果:
Configure.Instance.Configurer.ConfigureComponent(() => new ApprovalRepository(database), DependencyLifecycle.SingleInstance)
答案 0 :(得分:0)
在我的ApprovalRepository中,一些奇怪的代码已经悄悄进入,即:
#region Public Properties
public IApprovalRepository Repository { get; set; }
#endregion
NServiceBus然后试图自动注入该属性。因此,ApprovalRepository接收了IApprovalRepository。糟糕!我的错。这现在解释了错误:
Server.PlaceApprovalHandler -> Server.ApprovalRepository -> Server.ApprovalRepository
答案 1 :(得分:0)
在我看来,您尝试注入处理程序的具体类型应该是端点本身所不知道的。
https://code.google.com/p/autofac/wiki/Scanning
我喜欢通过在类上添加自定义属性来选择我的类型:
[AttributeUsage(AttributeTargets.Class)]
public class RegisterServiceAttribute : Attribute {}
然后选择如下类型:
builder.RegisterAssemblyTypes(assemblies)
.Where(t => t.GetCustomAttributes(typeof (RegisterServiceAttribute), false).Any())
.AsSelf()
.AsImplementedInterfaces();
作为我所做的一个例子:
public class EndpointConfig : IConfigureThisEndpoint, IWantCustomInitialization, AsA_Server, UsingTransport<SqlServer>
{
public void Init()
{
var builder = new ContainerBuilder();
builder.RegisterAssemblyTypes(GetAllAssemblies())
.Where(t => t.GetCustomAttributes(typeof(ProviderAttribute), false).Any())
.AsSelf()
.AsImplementedInterfaces();
Configure
.With()
.UseTransport<SqlServer>()
.AutofacBuilder(builder.Build())
.UseNHibernateTimeoutPersister()
.UseNHibernateSagaPersister()
.UnicastBus();
}
private static Assembly[] GetAllAssemblies()
{
var path = Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location);
return Directory.GetFiles(path, "*.dll").Select(Assembly.LoadFile).ToArray();
}
}