代码之家  ›  专栏  ›  技术社区  ›  Prisoner ZERO

使用structuremap配置具体类的属性

  •  1
  • Prisoner ZERO  · 技术社区  · 7 年前

    我有一组常用的电子邮件类 Application 实例。它们都共享相同的接口,但我需要能够(可选地)“填充”另一个“公共”类型的实例作为属性。

    从这里开始: 考虑到这个起点…
    注意,myapplication从所有3个属性开始。而且,由于DistributionListProvider是唯一配置的iInstanceProvider…因此不会出现问题。

    public class MyApplication : IMyApplication
    {       
        #region notifications
    
        [SetterProperty]
        public IEmailNotification RequestToFlowEmailNotification { get; set; }
    
        [SetterProperty]
        public IEmailNotification ApprovalToFlowEmailNotification{ get; set; }
    
        #endregion
    
        #region instance providers
    
        [SetterProperty]
        public IInstanceProvider DistributionListProvider { get; set; }
    
        #endregion
    }
    
    public class RequestToFlowEmailNotification : IEmailNotification
    {
        #region <Properties>
    
        [SetterProperty]
        public IInstanceProvider DistributionListProvider { get; set; }
    
        #endregion
    }
    
    public class ApprovalToFlowEmailNotification : IEmailNotification
    {
    
    }
    
    public class DistributionListProvider : ComponentProviderBase, IInstanceProvider
    {
    
    }
    

    让我们添加: 现在让我们创建另一个 iInstanceProvider安装程序 &将其添加到应用程序…
    但首先,请注意IEmailNotification&iInstanceProvider是常见类型,而不是“泛型类型”…这意味着它们不是 EmailNotificationFor<T> 类型。这使得在注册表中配置它们的方式有所不同。

    // NOW...LETS ADD THIS !!
    public class AuthorizationToFlowMeterDocumentRecallProvider : ComponentProviderBase, IInstanceProvider
    {
    
    }
    
    public class MyApplication : IMyApplication
    {       
        #region notifications
    
        [SetterProperty]
        public IEmailNotification RequestToFlowEmailNotification { get; set; }
    
        [SetterProperty]
        public IEmailNotification ApprovalToFlowEmailNotification{ get; set; }
    
        #endregion
    
        #region instance providers
    
        [SetterProperty]
        public IInstanceProvider DistributionListProvider { get; set; }
    
        [SetterProperty]
        public IInstanceProvider AuthorizationToFlowMeterDocumentRecallProvider{ get; set; }
    
        #endregion
    }
    

    此时,structuremap不再了解如何填充…

    • 请求LoweMailNotification.DistributionListProvider

    问:如何更新注册表以强制structuremap正确填充?
    下面是我的整个注册表…

    注:
    我不想设置默认值…有没有办法在不设置默认值的情况下执行此操作?

    public ContainerRegistry()
    {
        Scan(
            scan =>
            {
                scan.TheCallingAssembly();
                scan.WithDefaultConventions();
                scan.LookForRegistries();
                scan.SingleImplementationsOfInterface();
            });
    
        // ------------
        // UNIT OF WORK
        // ------------
        // DbContext
        For<DbContext>().Use<MeasurementContractsDbContext>();
    
        // UnitOfWork
        For<IMeasurementContractsUnitOfWork>().Use<MeasurementContractsUnitOfWork>();
    
        // GenericRepository
        For(typeof(ICompositeRepository<>)).Use(typeof(GenericRepository<>));
    
        // --------
        // HELPERS
        // --------
        For<IWindowsIdentityHelper>().Use<WindowsIdentityHelper>();
    
        For<ISmtpClientHelper>().Use<SmtpClientHelper>()
            .Ctor<ISmtpClient>().Is(new SmtpClient());
    
        For<IPdfConverterHelper>().Use<PdfConverterHelper>()
            .Ctor<IPdfConverterClient>().Is(new SelectPdfUrlConverterClient());
    
        // WARNING: Do not remove without replacing it with "some kind of" IConstructorSelector, so that, Unit Testing can be done
        For<IDataServiceFor<EmployeeData>>()
            .Use(x => new EmployeeDataService(new ODataProxyV4())); //<-- uses this constructor
    
        // --------
        // WORKFLOW
        // ---------
        For<IWorkflowProvider>().Use<WorkflowProvider>()
            .Ctor<Assembly>().Is(Assembly.GetExecutingAssembly());
    
        // --------
        // MANAGERS
        // --------
        For<IManager<Device>>().Use<DeviceManager>();
        For<IManager<Favorite>>().Use<FavoritesManager>();
        For<IManager<User>>().Use<UserManager>();
    
        // --------
        // DEPENDENCY MANAGERS
        // --------
        For<IDocumentDependency>().Use<DeviceAffinityProvider>();
    
        // --------
        // TRANSFORMERS
        // --------
        For<IXmlTransformerFor<AuthorizationToFlowMeterDocumentXmlDataSet>>().Use<AuthorizationToFlowMeterDocumentXmlTransformer>();
        For<IXmlTransformerFor<FirstDeliveryNoticeDocumentXmlDataSet>>().Use<FirstDeliveryNoticeDocumentXmlTransformer>();
        For<IXmlTransformerFor<RequestToFlowMeterDocumentXmlDataSet>>().Use<RequestToFlowMeterDocumentXmlTransformer>();
    
        // --------
        // PROVIDERS: DataItem Providers
        // --------
        For<IDataItemProviderFor<EmployeeData>>().Use<EmployeeDataProvider>();
    
        // --------
        // PROVIDERS: Document Providers
        // --------
        For<IDataItemProviderFor<RequestToFlowMeterDocument>>().Use<RequestToFlowMeterDocumentProvider>();
        For<IDataItemProviderFor<AuthorizationToFlowMeterDocument>>().Use<AuthorizationToFlowMeterDocumentProvider>();
        For<IDataItemProviderFor<FirstDeliveryNoticeDocument>>().Use<FirstDeliveryNoticeDocumentProvider>();
    
        // --------
        // COMMANDS
        // --------
        For<IAdminUpdateCommandFor<AuthorizationToFlowMeterDocument>>().Use<AuthorizationToFlowMeterDocumentAdminUpdateCommand>();
    
        // -----------
        // APPLICATION
        // -----------
        For<IMyApplication>().Use<MyApplication>()
    
            // Instance Provider
            .Setter(x => x.DistributionListProvider).Is<DistributionListProvider>()
            .Setter(x => x.AuthorizationToFlowMeterDocumentRecallProvider).Is<AuthorizationToFlowMeterDocumentRecallProvider>()
    
            // Email Notifications
            .Setter(x => x.ApprovalToFlowEmailNotification).Is<ApprovalToFlowEmailNotification>()
            .Setter(x => x.DenialToFlowEmailNotification).Is<DenialToFlowEmailNotification>()
            .Setter(x => x.ApprovalToFlowRecalledEmailNotification).Is<ApprovalToFlowRecalledEmailNotification>()
            .Setter(x => x.RequestToFlowEmailNotification).Is<RequestToFlowEmailNotification>()
            .Setter(x => x.FirstDeliveryNoticeEmailNotification).Is<FirstDeliveryNoticeEmailNotification>();
    }
    
    1 回复  |  直到 7 年前
        1
  •  2
  •   Nkosi    7 年前

    [SetterProperty] 属性时,StructureMap将尝试为属性生成并附加一个值,作为对象构造的一部分。

    但是,setter属性需要一个默认实现,因为它无法确定在有多个实现时要使用哪个实现,特别是在没有添加默认实现的情况下。

    RequestToFlowEmailNotification.DistributionListProvider 容器不知道要使用哪个实现。

    要重写此行为,请使用 请求LoweMailNotification.DistributionListProvider

    //...
    .Setter(x => x.RequestToFlowEmailNotification)
        .Is<RequestToFlowEmailNotification>(_ => 
            _.Setter(d => d.DistributionListProvider)
                .Is<DistributionListProvider>()); //<<-- change to which ever one is needed
    

    注意 Setter 设置的配置 RequestToFlowEmailNotification 然后是内在的 DistributionListProvider