2013-03-24 2 views
22

コンソールアプリケーションでは、Log4Netを使用しています。メインメソッドでは、ロガーオブジェクトを取得しています。さて、私はすべてのクラスがILogプロパティを持ち、コンストラクタインジェクションではなくプロパティインジェクションによって設定されるはずのBaseClassから継承するようにして、このログオブジェクトをすべてのクラスで利用できるようにしたいと思います。AutoFacでProperty Injectionを使用するには?

私はすべてのクラスのログプロパティに自分のログオブジェクトを挿入するには、AutoFac IoCコンテナを使用していますか?

これを達成する最も簡単な方法は何ですか?

タイプを自動的に解決する方法はありますか?

namespace ConsoleApplication1 
{ 
    class Program 
    { 
     static ILog Log; 
     static IContainer Container; 

     static void Main(string[] args) 
     {     
      InitializeLogger(); 

      InitializeAutoFac(); 

      // the below works but could it be done automatically (without specifying the name of each class)? 
      Product.Log = Container.Resolve<ILog>(); 

      // tried below but didn't inject ILog object into the Product 
      Container.Resolve<Product>(); 

      RunTest(); 

      Console.ReadLine(); 
     } 

     private static void RunTest() 
     { 
      var product = new Product(); 
      product.Do(); 
     } 

     private static void InitializeAutoFac() 
     { 
      var builder = new ContainerBuilder(); 

      builder.Register(c => Log).As<ILog>(); 

      builder.RegisterType<Product>().PropertiesAutowired(); 

      Container = builder.Build();    
     } 

     private static void InitializeLogger() 
     { 
      log4net.Config.XmlConfigurator.Configure(); 

      Log = LogManager.GetLogger("LoggerName"); 
     } 
    } 

    public class Product 
    { 
     public static ILog Log { get; set; } 

     public void Do() 
     { 
      // this throws exception because Log is not set 
      Log.Debug("some Debug"); 
     } 
    } 
} 
+1

をあなたはまた、あなたのクラスのそれぞれにロガーの静的インスタンスを作成することができます。こうすることで、各ロガーにはクラスが定義されたクラスの名前が自動的に付けられます。 – alex

+2

'Product'のIlogから' static'を削除します –

+0

私もインスタンスであることを試みましたが助けませんでした。 –

答えて

18

使用Property Injection

builder.Register(c => LogManager.GetLogger("LoggerName")) 
     .As<ILog>(); 

builder.RegisterType<CustomClass>() 
     .PropertiesAutowired(); 
+0

ありがとうございますが、ここにはどのようなLogクラスがありますか?私はILogインターフェイスを持っていると思う。 ILogオブジェクトは、LogManager.GetLogger( "LoggerName")から取得されます。 –

+0

@TheLight:私は再び、私の答えを編集した:) –

+0

良いおかげで、私は今)(container.Resolve でコンテナからログオブジェクトを見ることができます。どのようにAutoFacにそれを見ても自動的にILogを解決するように頼むことができますか?私のCustomClassのLogプロパティにアクセスすると、自動的に解決されず、例外がスローされます。 –

9

プロパティインジェクションがフィールドためプロパティないために働く

以下は私のテストアプリケーションです。あなたのクラスでは、Logはフィールドでありプロパティではないため、Autofacによって解決されることはありません。

18

私の意見では、Ninject createdのソリューションは、Autofacのpropertyinjectionよりはるかに良いです。私は質問の答えはすでに与えられている知っているが、私はこれはと思った

[Serializable] 
[AttributeUsage(AttributeTargets.Property, AllowMultiple = false)] 
public class AutofacResolveAttribute : LocationInterceptionAspect 
{ 
    public override void OnGetValue(LocationInterceptionArgs args) 
    { 
     args.ProceedGetValue(); 

     if (!args.Location.LocationType.IsInterface) return; 

     if (args.Value != null) 
     { 
      args.Value = DependencyResolver.Current.GetService(args.Location.LocationType); 
      args.ProceedSetValue(); 
     } 
    } 
} 

[AutofacResolve] 
public IStorageManager StorageManager { get; set; } 

マイ側面:したがって、私は自動的に私のクラスを注入postsharpの側面であるAAカスタム属性を作成しましたAutofacでの自動物性注入を解決する本当にきれいな方法。多分将来、誰かに役立つでしょう。

+1

upvote for creativity :) thx –

+0

ええ、私には便利です:) –

+0

ポストシャープの解決策はありますか? –

2

私はpostsharpを使いたくなかったので、私は簡単な解決策を作ったが、自動注入はしなかった。私はAutofacが初めてです。このソリューションを構築することは可能です。

[Serializable] 
[AttributeUsage(AttributeTargets.Property)] 
public class AutofacResolveAttribute : Attribute 
{ 
} 

public class AutofactResolver 
{ 
    /// <summary> 
    /// Injecting objects into properties marked with "AutofacResolve" 
    /// </summary> 
    /// <param name="obj">Source object</param> 
    public static void InjectProperties(object obj) 
    { 
     var propertiesToInject = obj.GetType().GetProperties() 
      .Where(x => x.CustomAttributes.Any(y => y.AttributeType.Name == nameof(AutofacResolveAttribute))).ToList(); 

     foreach (var property in propertiesToInject) 
     { 
      var objectToInject = Autofact.SharedContainer.Resolve(property.PropertyType); 
      property.SetValue(obj, objectToInject, null); 
     } 
    } 
} 

この呼び出しでそれを使用します。

AutofactResolver.InjectProperties(sourceObject); 
関連する問題