How to use Property Injection with AutoFac?

In a Console application, I'm using Log4Net and in the Main method I'm getting the logger object. Now, I'd like to make this log object available in all my classes by letting all the classes inherit from a BaseClass which has a ILog property and is supposed to be set by Property Injection rather than Constructor Injection.

I'm using AutoFac IoC container, how to inject my log Object to the Log property of my every class?

What's the best/easiest way to achieve this?

Is there any way to automatically resolve types?

Below is my test application:

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

In my opinion the solution Ninject created is much nicer than the propertyinjection in Autofac. Therefore I created aa custom attribute which is a postsharp aspect which automatically injects my classes:

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

My aspect:

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

I know the answer on the question is already given but I thought this was a really neat way of solving automatic property injection in Autofac. Maybe it'll be useful to somebody in the future.


使用属性注入:

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

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

Property injection works for Properties and not for Fields . In your class, Log is a field and not a property and hence it will never get resolved by the Autofac.

链接地址: http://www.djcxy.com/p/65666.html

上一篇: 如何在IOC容器中注册类型,但采用容器不可知的方式?

下一篇: 如何在AutoFac中使用Property注入?