property example c# asp.net inversion-of-control log4net autofac

property - autofac example c#



¿Cómo usar Property Injection con AutoFac? (4)

En mi opinión, la solución que created Ninject es mucho más agradable que la de inyección de propertyinjection en Autofac. Por lo tanto, creé un atributo personalizado que es un aspecto postsharp que inyecta automáticamente mis clases:

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

Mi aspecto:

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

Sé que la respuesta a la pregunta ya está dada, pero pensé que esta era una forma realmente ingeniosa de resolver la inyección automática de propiedades en Autofac. Tal vez sea útil para alguien en el futuro.

En una aplicación de consola, estoy usando Log4Net y en el método principal obtengo el objeto logger. Ahora, me gustaría hacer que este objeto de registro esté disponible en todas mis clases dejando que todas las clases se hereden de una Clase de base que tiene una propiedad ILog y se supone que se establece por Inyección de propiedades en lugar de Inyección de constructor.

Estoy usando AutoFac IoC container, ¿cómo inyectar mi objeto Log en la propiedad Log de cada clase?

¿Cuál es la forma mejor / más fácil de lograr esto?

¿Hay alguna forma de resolver automáticamente los tipos?

A continuación se muestra mi aplicación de prueba:

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


La inyección de propiedades funciona para Propiedades y no para Campos . En su clase, Log es un campo y no una propiedad y, por lo tanto, Autofac nunca lo resolverá.


No quería usar postsharp, así que hice una solución rápida, pero no se inyecta automáticamente. Soy nuevo en Autofac, y debería ser posible desarrollar esta solución.

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

Úsalo con esta llamada:

AutofactResolver.InjectProperties(sourceObject);


Use la inyección de la propiedad :

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