>

동일한 종속성 유형의 두 속성이있는 BasePage 클래스가 있는데 Autofac를 사용하여 필요한 매개 변수를 제공하는 방법을 찾을 수 없습니다

유형을 등록하려고했는데 BasePage 속성이 FaxSender와 같은 마지막으로 등록 된 동일한 구성 요소를 가리키고 있으며 TryGetDeclaringProperty 함수에 중단 점을 추가했으며 BasePage 클래스의 속성 이름을 확인하는 것이 좋습니다.

[업데이트 된 예]

public class BasePage : System.Web.UI.Page
{
    public ISender EmailSender { get; set; }
    public ISender FaxSender { get; set; }
}
public class EmailSender : ISender
{
    private readonly SmtpClient _smtpClient;
    public EmailSender(SmtpClient smtpClient)
    {
        _smtpClient = smtpClient;
    }
    public void Send(INotification notification)
    {
        //...
    }
}
public class FaxSender : ISender
{
    private readonly SmtpClient _smtpClient;
    public FaxSender(SmtpClient smtpClient)
    {
        _smtpClient = smtpClient;
    }
    public void Send(INotification notification)
    {
        //...
    }
}

Global.asax.cs

 var emailSmtp = new SmtpClient
        {
            ...
        };
        var emailSender = new EmailSender(emailSmtp);
        var faxSmtp = new SmtpClient
        {
            ...
        };
        var faxSender = new FaxSender(faxSmtp);
        var builder = new ContainerBuilder();
//--------------------------------
        builder.RegisterType<BasePage>()
            .WithProperties(new Parameter[]{
                new NamedPropertyParameter("EmailSender", emailSender),
                new NamedPropertyParameter("FaxSender", faxSender),
            });
 //--------------------------------  
    //OR
//--------------------------------
builder.RegisterType<EmailSender>()
            .Named<ISender>("email")
            .WithParameter("smtpClient", emailSmtp);
        builder.RegisterType<FaxSender>()
            .Named<ISender>("fax")
            .WithParameter("smtpClient", faxSmtp);
        builder.RegisterType<BasePage>()
            .AsSelf()
            .WithProperties(new Parameter[] {
                new ResolvedParameter(
                    (pi, c) => {
                        PropertyInfo ppi = null;
                        if (pi.TryGetDeclaringProperty(out ppi)) {
                            return ppi.Name == "EmailSender";
                        } else {
                            return false;
                        }
                    },
                    (pi, c) => c.ResolveNamed<ISender>("email")),
                new ResolvedParameter(
                    (pi, c) => {
                        PropertyInfo ppi = null;
                        if (pi.TryGetDeclaringProperty(out ppi)) {
                            return ppi.Name == "FaxSender";
                        } else {
                            return false;
                        }
                    },
                    (pi, c) => c.ResolveNamed<ISender>("fax"))
            });
//--------------------------------
//and then
        var container = builder.Build();
        _containerProvider = new ContainerProvider(container);
        using (var scope = container.BeginLifetimeScope())
        {
            scope.Resolve<BasePage>();
        }

Default.aspx.cs의

protected void Page_Load(object sender, EventArgs e)
{
    //Object reference not set to an instance of an object.  [Exception in both cases]
    EmailSender.Send(new EmailNotification(...);
    FaxSender.Send(new FaxNotification(...));
}

  • 답변 # 1

    Page 의 ASP.net 웹 양식 아키텍처로 인해  Autofac에 의해 인스턴스가 생성되지 않습니다. 페이지 인스턴스에 대한 등록을 구성 할 수 없습니다. 와이즈 비즈  이 경우에는 메소드가 사용되지 않습니다.

    귀하의 경우 한 가지 해결책은 종속성을 수동으로 해결하는 것입니다.

    당신의 WithProperty 에서  구성 요소

    BasePage
    
    

    또 다른 해결책은 public ISender EmailSender { get { var cpa = (IContainerProviderAccessor)this.Context.ApplicationInstance; return cpa.ContainerProvider.RequestLifetime.ResolveNamed<ISender>("email"); } } 를 사용하는 것입니다 . 2 개의 속성을 갖는 대신 모든 IIndex<TKey, TValue> 를 포함하는 속성을 하나만 가질 수 있습니다 .

    ISender
    
    

    특정 발신자가 필요할 때 다음을 통해 액세스 할 수 있습니다

    public IIndex<String, ISender> Senders {get; set; }
    
    

    예상 동작을 원하지만Autofac으로 생성 한 인스턴스의 경우 ISender emailSender = this.Senders["email"]; 를 사용해야합니다   NamedPropertyParameter 대신 .

    NamedParameter
    
    

    의존성 주입으로 값을 얻으려면 쉬운 방법이 없습니다.

    Autofac는이 확장 방법에 내부적으로 의존합니다 :

    // not working for webform !!! 
    builder.RegisterType<BasePage>()
           .WithProperties(new Parameter[]{
               new NamedPropertyParameter("X", emailSender),
               new NamedPropertyParameter("Y", faxSender),
           });
    
    

    그리고 당신은 public static class ParameterInfoExtensions { public static bool TryGetDeclaringProperty(this ParameterInfo pi, out PropertyInfo prop) { MethodInfo mi = pi.Member as MethodInfo; if (mi != (MethodInfo)null && mi.IsSpecialName && mi.Name.StartsWith("set_", StringComparison.Ordinal) && mi.DeclaringType != (Type)null) { prop = mi.DeclaringType.GetTypeInfo().GetDeclaredProperty(mi.Name.Substring(4)); return true; } prop = null; return false; } } 와 함께 사용할 수 있습니다  이 방법으로 :

    ResolvedParameter
    
    

    builder.RegisterType<EmailSender>() .Named<ISender>("email") .WithParameter("smtpClient", emailSmtp); builder.RegisterType<FaxSender>() .Named<ISender>("fax") .WithParameter("smtpClient", faxSmtp); builder.RegisterType<BasePage>() .AsSelf() .WithProperties(new Parameter[] { new ResolvedParameter( (pi, c) => { PropertyInfo ppi = null; if (pi.TryGetDeclaringProperty(out ppi)) { return ppi.Name == "SmtpClient"; } else { return false; } }, (pi, c) => c.ResolveNamed<ISender>("email")), new ResolvedParameter( (pi, c) => { PropertyInfo ppi = null; if (pi.TryGetDeclaringProperty(out ppi)) { return ppi.Name == "FaxClient"; } else { return false; } }, (pi, c) => c.ResolveNamed<ISender>("fax")) });

  • 이전 typescript - 'typeof '유형의 인수는 'new () => '유형의 매개 변수에 지정할 수 없습니다
  • 다음 currency - 프로그래밍 방식으로 암호 화폐 이전