【问题标题】:C# Dependency Injection with StructureMap使用 StructureMap 进行 C# 依赖注入
【发布时间】:2012-09-19 20:48:50
【问题描述】:

我们一直在使用 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 文件中代码的 sn-p:

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 类型的 IAlertGenerator 的 IEnumerable 注入到我的 CustomResolver 中,但是我收到一个 StructureMap 202 异常,指出没有找到该类型的默认实例,即使我创建了实例它在 StructureMap 初始化文件的最后一个条目中。

这是我运行它时收到的错误消息的副本:

StructureMap 异常代码:202 未定义默认实例 插件家族 System.Collections.Generic.IEnumerable1[[Core.Domain.Alerts.IAlertGenerator1[[Core.Domain.Model.Customer, 核心,版本=1.0.0.0,文化=中性,PublicKeyToken=null]],核心, 版本=1.0.0.0,文化=中性,PublicKeyToken=null]],mscorlib, 版本=4.0.0.0,文化=中性,PublicKeyToken=b77a5c561934e089

谁能提供有关如何解决此问题的建议?

【问题讨论】:

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


    【解决方案1】:

    除了Mike has pointed out 这个问题可能是由多个实例关闭类型引起的。根据您的代码:

    ObjectFactory.GetInstance<IEnumerable<IAlertGenerator<Customer>>>()
    

    我猜这就是正在发生的事情。

    应该像把上面改成这样简单:

    ObjectFactory.GetAllInstances<IAlertGenerator<Customer>>()
    

    这将找到所有关闭IAlertGenerator&lt;Customer&gt;的实例。

    【讨论】:

      【解决方案2】:

      我不能 100% 确定这里发生了什么,但在收到此错误时,我在 StructureMap 中看到了两个不同的问题。首先是被实例化的类需要一个无参构造函数,所以Customer可能没有。

      第二个问题是,即使存在无参数构造函数,StructureMap 也会尝试使用最完全合格的构造函数,而我已经在 SqlConnection 之类的类中看到了这一点。以下是如何解决此问题的示例。

      x.ForRequestedType<IDbConnection>()
          .CacheBy(InstanceScope.Singleton)
          .TheDefault.Is.ConstructedBy(ctor => new SqlConnection("connection string"));
      

      请注意,我必须使用 .TheDefault.Is.ConstructedBy 构造才能让它使用正确的构造函数。在诉诸于此之前,我曾尝试使用 .Ctor 构造传递参数,但无法使其正常工作。

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2012-12-17
        • 1970-01-01
        • 1970-01-01
        • 2015-09-26
        • 2014-01-19
        • 2014-03-25
        • 2019-11-21
        • 1970-01-01
        相关资源
        最近更新 更多