6

log4net を必要とするすべてのクラスに登録するために、次のコードを使用します。

public class LogInjectionModule : Module
{
    private readonly string _configPath;

    public LogInjectionModule(string configPath)
    {
        _configPath = configPath;
    }

    protected override void AttachToComponentRegistration(IComponentRegistry registry,
        IComponentRegistration registration)
    {
        XmlConfigurator.Configure(new FileInfo(_configPath));

        registration.Preparing += OnComponentPreparing;
    }

    private static void OnComponentPreparing(object sender, PreparingEventArgs e)
    {
        var t = e.Component.Activator.LimitType;
        e.Parameters = e.Parameters.Union(new[]
                                          {
                                              new ResolvedParameter((p, i) => p.ParameterType == typeof (ILog),
                                                  (p, i) => LogManager.GetLogger(t))
                                          });
    }
}

すべてのクラスは、autofac の型スキャンを使用して登録されます。

builder.RegisterAssemblyTypes(typeof (IResourceFinder).Assembly)
 .AsImplementedInterfaces();

そして、それはうまくいきます!

1 つのクラスを明示的に登録する必要があり、ILog を解決しようとして失敗します

builder.Register(x => new ClassThatNeedsILog(x.Resolve<ILog>())).AsImplementedInterfaces();

これがそのクラスです

public class ClassThatNeedsILog
{
    public ClassThatNeedsILog(ILog log)
    {

    }
}

次の例外が発生します。

Autofac.Core.Registration.ComponentNotRegisteredException : 要求されたサービス 'log4net.ILog' は登録されていません。この例外を回避するには、コンポーネントを登録してサービスを提供するか、IsRegistered() を使用してサービス登録を確認するか、ResolveOptional() メソッドを使用してオプションの依存関係を解決します。

4

3 に答える 3

13

LogInjectionModule コンテナーに登録することはありませんILog。 準備中の面で解決されたインスタンスのパラメーターを提供するだけであり、Autofac によって作成されたインスタンスに対してのみ機能します。

したがって、書くときは手動でbuilder.Register(x => new ClassThatNeedsILog(x.Resolve<ILog>()))作成しています。ClassThatNeedsILognew ClassThatNeedsILog(...)

したがって、Autofac はインスタンスの作成を認識せず (したがって、実行されません)、実装をOnComponentPreparing実際に登録していないため、 .ILogComponentNotRegisteredException

次の 2 つのオプションがあります。

  • ILogをコンテナに直接登録する
  • Autofac にClassThatNeedsILog型を作成させます。

ILogしたがって、コンテナに次のように登録できます。

builder.RegisterInstance(LogManager.GetLogger("Logger")).As<ILog>();

その後、コードは正常に動作します。

または、とにかく手動で作成する場合はClassThatNeedsILog、そこに直接供給することができますILog

 builder.Register(x => new 
     ClassThatNeedsILog(LogManager.GetLogger(typeof(ClassThatNeedsILog))))
     .AsImplemen‌​tedInterfaces();

他のオプションは、Autofac にインスタンスを作成させることなので、登録を次のように変更します。

 builder.RegisterType<ClassThatNeedsILog>()
     .AsImplemen‌​tedInterfaces();

この場合、Autofac がインスタンスの作成を処理し、OnComponentPreparingモジュールのメソッドを呼び出します。

追加のコンストラクタ パラメータを指定する場合は、メソッドWithParameterWithParametersメソッドを使用できます。

 builder.RegisterType<ClassThatNeedsILog>()
     .AsImplemen‌​tedInterfaces()
     .WithParameters(new Parameter[] {
         ResolvedParameter.ForNamed<IAnotherInterface>("NAME"),
         ResolvedParameter.ForNamed<IYetAnotherInterface>("ANOTHERNAME")});
于 2013-11-08T06:30:42.930 に答える
0

それができる前にbuilder必要です。BuildcontainerResolve

このようなことを試してください(テストされていません)

builder
    .RegisterAssemblyTypes(typeof (IResourceFinder).Assembly)
    .AsImplementedInterfaces();
/* process LogInjectionModule */
IContainer container = builder.Build();

var updateBuilder = new ContainerBuilder();
updateBuilder
    .Register(x => new ClassThatNeedsILog(x.Resolve<ILog>()))
    .AsImplementedInterfaces();
updateBuilder.Update(container);
于 2013-11-05T10:41:33.027 に答える
0

nemesvの回答で問題が解決しました。

ただし、以下が欠けていたため、RegisterTypeアプローチを使用した後、それを機能させるためにもう少し時間を費やす必要がありました。

config.Filters.AddRange(config.DependencyResolver.GetServices(typeof(IExceptionFilter)).Select(o => o as IExceptionFilter));

他の人が最初にフィルターを設定するのを忘れた場合は、ここに言及するだけです。

于 2016-03-13T00:36:40.520 に答える