2013-03-24 22 views
22

Bir Konsol uygulamasında Log4Net kullanıyorum ve Ana yöntemde kaydedici nesnesini alıyorum. Şimdi, tüm sınıfları, tüm sınıfların bir ILog özelliğine sahip olan ve Constructor Injection'dan ziyade Property Injection tarafından ayarlanması gereken bir BaseClass'dan miras almasına izin vererek bu sınıf nesnesini bütün sınıflarımda kullanılabilir hale getirmek istiyorum.AutoFac ile Mülkiyet Enjeksiyonu Nasıl Kullanılır?

AutoFac IoC kapsayıcısı kullanıyorum, günlük Nesnemi her sınıfımın Log özelliğine nasıl enjekte edebilirim?

Bunu başarmanın en iyi/en kolay yolu nedir?

Türleri otomatik olarak çözmenin bir yolu var mı?

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

. Bu şekilde, her bir kaydedici otomatik olarak tanımlandığı sınıfın ismine sahip olacaktır. – alex

+2

'Product' –

+0

'da 'static' ilog'undan çıkarmayı deneyin. Örnek olmakla çalıştım ama yardımcı olmadım. –

cevap

18

Kullanım Property Injection:

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

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

teşekkürler ama burada Log sınıfı nerede/nerede? Sadece düşündüğüm ILog arayüzüne sahibim. ILog nesnesi LogManager.GetLogger'dan ("LoggerName") alınır; –

+0

@TheLight: Cevabımı tekrar düzenledim :) –

+0

iyi teşekkürler, şimdi kapsayıcıdan kapsayıcıdan günlük nesnesini görebiliyorum. () öğesini yeniden deneyin. fakat AutoFac'tan ILog'u nerede gördüğü her yerde otomatik olarak çözmesini nasıl isteyebilirim? Otomatik olarak çözülmez ve CustomClass'ımda Log özelliğine eriştiğimde şu anda istisna atar. –

9

Mülkiyet enjeksiyon Fields için Özellikleri değil çalışır

Aşağıda benim test uygulamasıdır. Sınıfınızda, Log bir alan değil, bir mülktür ve dolayısıyla Autofac tarafından asla çözülmez.

18

Benim düşünceme göre Ninpes created çözümü, Autofac içinde propertyinjection'dan çok daha güzel. Bu nedenle ben kendi sınıfları enjekte eden bir postsharp yönüdür aa özel bir özellik oluşturuldu:

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

My boy:

[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(); 
     } 
    } 
} 

ben soru üzerine cevabını biliyorum zaten verilmiş ama bu bir oldu düşünülmektedir Autofac içinde otomatik özellik enjeksiyonunu çözmek için gerçekten temiz bir yol. Belki gelecekte birileri için yararlı olacaktır.

+1

Yaratıcılığım için daha fazlası :) thx –

+0

Evet, bana faydalı :) –

+0

Mesaj paylaşım olmadan bir çözüm var mı? –

2

Hızlı bir çözüm hazırladığımdan postharp kullanmak istemedim, ancak otomatik olarak enjekte etmiyor. Autofac'a yeniyim ve bu çözüme dayanabilmeli.

[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); 
     } 
    } 
} 

bu çağrıyla kullanın: Ayrıca sınıfların her birinde kaydedici statik örneğini oluşturabilir

AutofactResolver.InjectProperties(sourceObject);