使用StructureMap进行C#依赖注入

时间:2012-09-19 20:48:51

标签: c# asp.net-mvc-3 structuremap

我们在使用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

任何人都可以提供有关如何解决此问题的建议吗?

2 个答案:

答案 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构造传递参数,但却无法使其工作。

我希望这有助于指明你正确的方向。