我们在使用C#的ASP.Net MvC 3 Web应用程序中一直使用StructureMap进行依赖注入,但今天我无法将所需的类型注入到我构建的C#CustomResolver中。
以下是StructureMapInitialization.cs文件中的代码:
namespace UI.DependencyResolution
{
/// <summary>
/// Class Structure Map IOC intialization
/// </summary>
public static class StructureMapIocInitialization
{
/// <summary>
/// Initialize Method for Structure Map IOC Initialization
/// </summary>
/// <returns>an IContainer for Services and Repository</returns>
public static IContainer Initialize()
{
ObjectFactory.Initialize(cfg =>
{
cfg.Scan(scan =>
{
scan.Assembly("Infrastructure");
scan.Assembly("Core");
scan.WithDefaultConventions();
scan.ConnectImplementationsToTypesClosing(typeof(IAlertGenerator<>));
scan.ConnectImplementationsToTypesClosing(typeof(IValidationRule<>));
});
cfg.For<IFilterProvider>().Use<StructureMapFilterProvider>();
cfg.For<IControllerActivator>().Use<StructureMapControllerActivator>();
cfg.SetAllProperties(c =>
{
c.WithAnyTypeFromNamespaceContainingType<ICustomerRepository>();
c.WithAnyTypeFromNamespaceContainingType<IMachineRepository>();
c.WithAnyTypeFromNamespaceContainingType<ICurrentUserService>();
c.WithAnyTypeFromNamespaceContainingType<ICircuitRegistrationRepository>();
c.WithAnyTypeFromNamespaceContainingType<IWorkflowRequestInformationRepository>();
c.WithAnyTypeFromNamespaceContainingType<IEnumerable<IAlertGenerator<Customer>>>();
});
});
return ObjectFactory.Container;
}
}
}
以下是我们的AutoMapperProfile.cs文件中的代码片段:
Mapper.CreateMap<AbstractOrganization, DashboardDetails>()
.ForMember(dashboard => dashboard.AlertsDictionary,
member => member.ResolveUsing<OrganizationAlertResolver>()
.ConstructedBy(() => new OrganizationAlertResolver(
ObjectFactory.GetInstance<ICustomerRepository>(), ObjectFactory.GetInstance<IEnumerable<IAlertGenerator<Customer>>>())));
这是我的CustomResolver代码:
namespace UI.Models.CustomResolvers
{
public class OrganizationAlertResolver : ValueResolver<Organization, Dictionary<string, string>>
{
private readonly ICustomerRepository _customerRepository;
/// <summary>
/// Storage for customer alert generator.
/// </summary>
private readonly IEnumerable<IAlertGenerator<Customer>> _customerAlertGenerators;
public OrganizationAlertResolver(ICustomerRepository customerRepository,
IEnumerable<IAlertGenerator<Customer>> customerAlertGenerators)
{
_customerRepository = customerRepository;
_customerAlertGenerators = customerAlertGenerators;
}
protected override Dictionary<string,string> ResolveCore(Organization organization)
{
var customers = _customerRepository.GetActiveCustomersByOrgNumber(organization.OrgNumber);
foreach (var generator in _customerAlertGenerators)
{
generator.PopulateAlerts(customers);
}
Dictionary<string, string> alertsDictionary = new Dictionary<string, string>();
foreach (var customer in customers)
{
foreach (var alert in customer.Alerts)
{
if(alertsDictionary.ContainsKey(alert.ToString()))
{
alertsDictionary[alert.ToString()] = alert.Message;
}
else
{
alertsDictionary.Add(alert.ToString(), alert.Message);
}
}
}
return alertsDictionary;
}
}
}
所以,我正在尝试使用StructureMap将类型为Customer的IElertGenerator的IEnumerable注入到我的CustomResolver中,但是我得到一个StructureMap 202 Exception,表示找不到该类型的默认实例,即使我创建了实例它在StructureMap初始化文件的最后一个条目中。
以下是我运行时收到的错误消息的副本:
StructureMap异常代码:202没有定义默认实例 PluginFamily System.Collections.Generic.IEnumerable
1[[Core.Domain.Alerts.IAlertGenerator
1 [[Core.Domain.Model.Customer, Core,Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null]],Core, Version = 1.0.0.0,Culture = neutral,PublicKeyToken = null]],mscorlib, Version = 4.0.0.0,Culture = neutral,PublicKeyToken = b77a5c561934e089
任何人都可以提供有关如何解决此问题的建议吗?
答案 0 :(得分:2)
除了Mike has pointed out此问题可能由关闭该类型的多个实例引起。根据您的代码:
ObjectFactory.GetInstance<IEnumerable<IAlertGenerator<Customer>>>()
我猜这就是发生的事情。
应该像将上述内容更改为:
一样简单ObjectFactory.GetAllInstances<IAlertGenerator<Customer>>()
将找到关闭IAlertGenerator<Customer>
的所有实例。
答案 1 :(得分:0)
我不是百分之百确定这里发生了什么,但是在收到此错误时我在StructureMap中看到了两个不同的问题。第一个是被实例化的类需要一个无参数构造函数,因此Customer
可能没有。{/ p>
第二个是,即使存在无参数构造函数,StructureMap也会尝试使用最完全限定的构造函数,并且我已经看到类似SqlConnection
的类。下面是一个如何解决这个问题的例子。
x.ForRequestedType<IDbConnection>()
.CacheBy(InstanceScope.Singleton)
.TheDefault.Is.ConstructedBy(ctor => new SqlConnection("connection string"));
请注意,我必须使用.TheDefault.Is.ConstructedBy
构造来使其使用正确的构造函数。在诉诸于此之前,我试图仅使用.Ctor
构造传递参数,但却无法使其工作。
我希望这有助于指明你正确的方向。