Requiring an attribute for CastleWindsor property injection - c#

Although I prefer constructor injection, I want developers on my team to be able to use property injection as long as they explicitly mark the property as injectable with an attribute. According to CastleWindsor documentation here, this should be possible by creating a contributor and then calling AddContributor with it through the Kernel. I cannot seem to get this to work. All public properties (even those without the attribute) are injected.
When I set a breakpoint in my contributor ProcessModel method, it sets all properties with the attribute to mandatory (IsOptional = false) and skips over any properties that do not have the attribute. But despite this, the properties without the attribute still get injected. What am I doing wrong?
Below is my code:
Contributor
public class PropertyInjectionContributor : IContributeComponentModelConstruction
{
public void ProcessModel(IKernel kernel, ComponentModel model)
{
model.Properties
.Where(p => p.Property.IsDefined(typeof(InjectedAttribute)))
.All(p => p.Dependency.IsOptional = false);
}
}
Attribute
[AttributeUsage(AttributeTargets.Property)]
public class InjectedAttribute : Attribute { }
Add contributor to Kernel.ComponentModelBuilder and register components
public class Program
{
public static void Main(string[] args)
{
var container = new WindsorContainer();
container.Kernel.ComponentModelBuilder.AddContributor(new PropertyInjectionContributor());
container.Register(Component.For<IClass1>()
.ImplementedBy<Class1>()
.LifestyleTransient());
container.Register(Component.For<IClass2>()
.ImplementedBy<Class2>()
.LifestyleTransient());
var class1 = container.Resolve<IClass1>();
class1.DoSomething();
}
}
Class1
public class Class1 : IClass1
{
//[Injected]
public IClass2 Class2 { get; set; }
public void DoSomething()
{
Class2.DoSomething();
}
}
The Class2 property within Class1 is injected even though it is not decorated with the Injected attribute.
My current workaround for this is to remove CastleWindsor's PropertiesDependenciesModelInspector and replace it with an implementation that forces IsOptional to be false. It works but it repeats a lot of CW's code. I'd prefer to use the simple approach above if I can only get it to work!

Related

Inject property with value from another property of another registered object?

I'm not so sure that DryIoc is worth my time. It looks like lightweight and supported well in cross-platform environment (with Xamarin). But I feel a bit difficult working with it (in term of exploring everything myself).
The DryIoc community is also not very large (and by reading through some answers about DryIoc, I recognized that looks like there is only the author jumping in and giving the answers). Here is my problem as mentioned in the title. Suppose I have 2 ViewModel classes, the second has a property which should always match (mapped) with a property of the first, like this:
public class ParentViewModel {
}
public class FirstViewModel {
public FirstViewModel(ParentViewModel parent){
}
public string A {
//...
}
}
public class SecondViewModel {
public SecondViewModel(ParentViewModel parent){
}
public string A {
//...
}
}
Now I can use dryioc to register singleton for both ViewModels BUT for the second one, I also need to inject the property A with value from the first's property A as well.
container.Register<ParentViewModel>();
container.Register<FirstViewModel>(reuse: Reuse.Singleton, made: Made.Of(() => new FirstViewModel(Arg.Of<ParentViewModel>())));
container.Register<SecondViewModel>(reuse: Reuse.Singleton, made: Made.Of(() => new SecondViewModel(Arg.Of<ParentViewModel>())));
So as you can see the first registration should be fine because no property dependency is required. However the second one should have its A property depend on the A of the first one.
Really I cannot explore this myself. Injecting properties of some registered type is fine (and at least I know how to do that), but here the injected value is another property of some registered type.
Here is the straightforward way (but may be not the best one) to achieve that:
using System;
using DryIoc;
public class Program
{
public static void Main()
{
var container = new Container();
container.Register<ParentViewModel>();
container.Register<FirstViewModel>(Reuse.Singleton);
container.Register<SecondViewModel>(Reuse.Singleton,
made: PropertiesAndFields.Of.Name("A", r => r.Container.Resolve<FirstViewModel>().A));
var firstVM = container.Resolve<FirstViewModel>();
firstVM.A = "blah";
var secondVM = container.Resolve<SecondViewModel>();
Console.WriteLine(secondVM.A); // should output "blah"
}
public class ParentViewModel {
}
public class FirstViewModel {
public FirstViewModel(ParentViewModel parent) { }
public string A { get; set; }
}
public class SecondViewModel {
public SecondViewModel(ParentViewModel parent) {}
public string A { get; set; }
}
}
In my opinion, the better and more simple way will the inversion of control: creating the A outside of both VMs and then injecting them into both.

Ninject interception proxying class with non empty constructor via castle dynamic proxy

I am basing most of my current implementation off the information provided here:
Ninject Intercept any method with certain attribute?
I use a custom planning strategy class which looks for all methods with given attributes (not ninject interceptor attributes) which will then get proxied if it matches the criteria.
An example of usage would be:
Kernel.Components.Add<IPlanningStrategy, CustomPlanningStrategy<LoggingAttribute, LoggerInterceptor>>();
This would then look for any methods which have a [Logging] attribute and will then use the logging interceptor.
However I am currently getting InvalidProxyConstructorArgumentsException from dynamic proxy when it is trying to proxy the methods with related attributes on. Now I remember reading that you need virtual methods, however I do not remember seeing that you HAD to have a parameterless constructor.
All bindings are done against interfaces, and the AOP interceptors happen via attributes and the custom proxy planning class mentioned in the link above.
So is there a way to get dynamic proxy (or the linfu version) to proxy the classes which have constructors with dependencies? (All dependencies are in the Kernel so its not like they cannot be resolved).
Looking at the proxy generating code:
https://github.com/ninject/ninject.extensions.interception/blob/master/src/Ninject.Extensions.Interception.DynamicProxy/DynamicProxyProxyFactory.cs
if (targetType.IsInterface)
{
reference.Instance = this.generator.CreateInterfaceProxyWithoutTarget(targetType, additionalInterfaces, InterfaceProxyOptions, wrapper);
}
else
{
object[] parameters = context.Parameters.OfType<ConstructorArgument>()
.Select(parameter => parameter.GetValue(context, null))
.ToArray();
reference.Instance = this.generator.CreateClassProxy(targetType, additionalInterfaces, ProxyOptions, parameters, wrapper);
}
one can see that ninject's dynamic proxy extension is only passing ConstructorArguments to the Castle Dynamic Proxy Generator.
So - without changes to the ninject extension or creating your own - you need to pass all dependencies as constructor arguments. You could also try out whether property / method injection works (see https://github.com/ninject/ninject/wiki/Injection-Patterns).
If you control the code you could add interfaces to the proxied classes and then use an "interface proxy with target". This allows to decouple proxy instantiation from target (proxied class) instantiation --> target can have dependencies ctor injected without any changes to ninject (-extensions).
Clarification:
Having the following class which should be proxied:
public interface IBar { }
public class Foo
{
public Foo(IBar bar)
{
}
}
And the following binding:
Bind<Foo>().ToSelf().Intercept().With<SomeInterceptor>();
Bind<IBar>().To<Bar>();
And then retrieving a Foo from the ninject container:
IResolutionRoot.Get<Foo>();
won't work.
Putting all constructor arguments on the ninject context to make it work
However, we can change the retrieving of Foo to make it work:
var bar = IResolutionRoot.Get<IBar>();
IResolutionRoot.Get<Foo>(new ConstructorArgument("bar", bar);
Now this is suboptimal because ninject is not doing dependency resolution automatically.
Adding interface to proxied class to make it work better
We can work around the issue by using a "interface proxy with target".
First, we add an interface to the proxied class:
public interface IFoo{ }
public class Foo : IFoo
{
public Foo(IBar bar)
{
}
}
And then we change the binding to:
Bind<IFoo>().To<Foo>().Intercept().With<SomeInterceptor>();
And then retrieving a Foo from the ninject container:
IResolutionRoot.Get<Foo>();
works.
Another, possibly easier (&uglier?) solution
According to #Daniel this works:
Add two constructor to the proxied type:
one protected constructor without parameters. This one is for DynamicProxy to create the proxy.
one public/internal constructor with the arguments, to be used by ninject to instantiate the proxied type.
Ninject will automatically pick the constructor with the most arguments it can resolve.
An alternate approach would be to use a convention based binding for all classes with a method with a [Logging] attribute. However, this means that adding a [Logging] attribute to a method will influence the binding of the object, which may be undesired.
So this is how it would work (verified to work):
[AttributeUsage(AttributeTargets.Method, AllowMultiple = false)]
public sealed class LoggingAttribute : Attribute
{
}
public interface IClassNotToBeIntercepted
{
void DoSomething();
}
public class ClassNotToBeIntercepted : IClassNotToBeIntercepted
{
public void DoSomething() { }
}
public interface IClassToBeIntercepted
{
void DoNotLogThis();
void LogThis();
void LogThisAsWell();
}
public class ClassToBeIntercepted : IClassToBeIntercepted
{
public void DoNotLogThis() { }
[Logging]
public void LogThis() { }
[Logging]
public void LogThisAsWell() { }
}
public class LoggingInterceptor : IInterceptor
{
public void Intercept(IInvocation invocation)
{
Console.WriteLine("interceptor before {0}", BuildLogName(invocation));
invocation.Proceed();
Console.WriteLine("interceptor after {0}", BuildLogName(invocation));
}
private static string BuildLogName(IInvocation invocation)
{
return string.Format(
"{0}.{1}",
invocation.Request.Target.GetType().Name,
invocation.Request.Method.Name);
}
}
public class DemoModule : NinjectModule
{
public override void Load()
{
this.Bind(convention => convention
.FromThisAssembly()
.SelectAllClasses()
.Where(ContainsMethodWithLoggingAttribute)
.BindDefaultInterface()
.Configure(x => x
.Intercept()
.With<LoggingInterceptor>()));
this.Bind<IClassNotToBeIntercepted>()
.To<ClassNotToBeIntercepted>();
}
private static bool ContainsMethodWithLoggingAttribute(Type type)
{
return type
.GetMethods()
.Any(method => method.HasAttribute<LoggingAttribute>());
}
}
And a test:
[Fact]
public void InterceptorTest()
{
var kernel = new StandardKernel();
kernel.Load<DemoModule>();
kernel.Get<IClassNotToBeIntercepted>()
.DoSomething();
kernel.Get<IClassToBeIntercepted>()
.LogThis();
}
Results in the following console output:
interceptor before ClassToBeIntercepted.LogThis
interceptor after ClassToBeIntercepted.LogThis

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 a a 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.
Use Property Injection:
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.
I didn't want to use postsharp so I made a quick solution, but it doesn't auto inject. I am new to Autofac, and it should be possible to build on to this solution.
[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);
}
}
}
Use it with this call:
AutofactResolver.InjectProperties(sourceObject);
Use Property Injection (In addition to #cuongle answer).
Option 1:
builder.Register(c => LogManager.GetLogger("LoggerName")).As<ILog>();
builder.RegisterType<Product>()
.WithProperty("Log", LogManager.GetLogger("LoggerName"));
Option 2:
Or you can add a SetLog method to the Product class:
public class Product
{
public static ILog Log { get; set; }
public SetLog(Log log)
{
this.Log = log;
}
}
This way you won't have to call LogManager.GetLogger("LoggerName") twice but to use the context of the builder in order to resolve the Log.
builder.Register(c => LogManager.GetLogger("LoggerName")).As<ILog>();
builder.Register(c =>
var product = new Product();
product.SetLog(c.Resolve<Log>());
return product;
);
Option 3:
Use the OnActvated:
The OnActivated event is raised once a component is fully constructed.
Here you can perform application-level tasks that depend on the
component being fully constructed - these should be rare.
builder.RegisterType<Product>()
.OnActivated((IActivatedEventArgs<Log> e) =>
{
var product = e.Context.Resolve<Parent>();
e.Instance.SetParent(product);
});
These options gives more control, and you will not have to worry about #steven comment:
The scary thing with PropertiesAutowired however is that it does
implicit property injection, which means that any unresolvable
dependencies will be skipped. This makes it easy to miss configuration
errors and can result in application that fails at runtime
There is an interface IPropertySelector that you can implement and pass the implementaiton via .PropertiesAutowired(new MyPropertySelector()). This will allow you to implement any logic you want.

Providing Ninject with constructor dependencies it can't resolve?

Disclaimer: I'm quite new to DI and IoC, please forgive any drastic misunderstandings.
Consider a ClassB that requires a object implementing IClassA. Ninject should be able to inject instances of ClassA into the constructor of ClassB, assuming it can construct instances of ClassA:
public class ClassA : IClassA
{
public ClassA(string runtimeDependency) { /* ... */ }
}
public class ClassB : IClassB
{
public ClassB(IClassA depA) { /* ... */ }
}
public sealed class TestBootstrapModule : NinjectModule
{
public override void Load()
{
Bind<IClassA>().To<ClassA>();
Bind<IClassB>().To<ClassB>();
}
}
Now, let's say some runtime logic is involved in deriving the string runtimeDependency provided to ClassA. How should I provide Ninject with runtimeDependency so that it can provide ClassB with instances of ClassA?
The string will only be determined once, so I don't need to worry about injecting a new value into each instance.
One way to do it is to provide the ClassA via a method. Also keep in mind that with Ninject 2, you don't need modules and can do bindings directly in the Kernel.
Bind<IClassA>().ToMethod(_ =>
{
// do something interesting with a runtimeDependancy
return new ClassA(someInterestingVariable);
});
I'm really taking a stab as to when your runtime variable is available and it's scope.
There are a few options here depending on your design, and specific problem. The first, easiest solution is to just provide the value when you request your service from Ninject
Kernel.Get<IClassA>("runtimeDependencyValue");
If this is not possible however, things get a bit more interesting. The way I've solved this previously is to actually create contextual bindings to System.String itself.
Say if I want to bind a connection string, I'll create a custom attribute:
[AttributeUsage(AttributeTargets.Parameter | AttributeTargets.Property, AllowMultiple = false, Inherited = true)]
public class ConnectionStringAttribute : Attribute
{
/// <summary>
/// Denotes the setting that you want to populate the given property with.
/// </summary>
public string SettingName { get; private set; }
public ConnectionStringAttribute(string configSettingName = "")
{
SettingName = configSettingName;
}
}
and then I decorate my service constructor like this:
public class ClassA : IClassA
{
public ClassA([ConnectionString("AppDB")] string runtimeDependency) { /* ... */ }
}
Finally, my binding will look something like this:
Bind<string>()
.ToMethod(ctx =>
{
var attr = (ConnectionStringAttribute)context.Request.Target.GetCustomAttributes(typeof(ConnectionStringAttribute), true).First();
string settingName = string.IsNullOrEmpty(attr.SettingName) ? context.Request.Target.Name : attr.SettingName;
return ConfigurationManager.ConnectionStrings[settingName].ConnectionString;
})
.WhenTargetHas<ConnectionStringAttribute>();
You get the idea. Hope this helps :)

Configuring an Autofac delegate factory that's defined on an abstract class

I'm working on a C# project. I'm trying to get rid of a Factory class that has a large switch statement.
I want to configure Autofac to be able to construct a dependency based on a parameter, thereby allowing Autofac to take the place of the Factory.
I've looked at the DelegateFactories page of the Autofac wiki, but I can't figure out how to apply the pattern to an abstract class. Here's some code showing the situation:
public enum WidgetType
{
Sprocket,
Whizbang
}
public class SprocketWidget : Widget
{
}
public class WhizbangWidget : Widget
{
}
public abstract class Widget
{
public delegate Widget Factory(WidgetType widgetType);
}
public class WidgetWrangler
{
public Widget Widget { get; private set; }
public WidgetWrangler(IComponentContext context, WidgetType widgetType)
{
var widgetFactory = context.Resolve<Widget.Factory>();
Widget = widgetFactory(widgetType);
}
}
I'd like it if I were to say new WidgetWrangler(context, WidgetType.Sprocket), its Widget property would be a SpocketWidget.
When I try this, I get errors stating that Widget.Factory is not registered. Does this delegate factory pattern not work with abstract classes, and if so, is there another way to accomplish this?
What you're looking for is the IIndex<,> Relationship Type.
If you register your sub-classes with .Keyed<>(...) you can key a registration to a value (object).
For example:
builder.RegisterType<SprocketWidget>()
.Keyed<Widget>(WidgetType.Sproket)
.InstancePerDependency();
builder.RegisterType<WhizbangWidget>()
.Keyed<Widget>(WidgetType.Whizbang)
.InstancePerDependency();
Then you only require a dependency of IIndex<WidgetType,Widget> to mimic factory behaviour.
public class SomethingThatUsesWidgets
{
private readonly IIndex<WidgetType,Widget> _widgetFactory;
public SomethingThatUsesWidgets(IIndex<WidgetType,Widget> widgetFactory)
{
if (widgetFactory == null) throw ArgumentNullException("widgetFactory");
_widgetFactory = widgetFactory;
}
public void DoSomething()
{
// Simple usage:
Widget widget = widgetFactory[WidgetType.Whizbang];
// Safe Usage:
Widget widget2 = null;
if(widgetFactory.TryGetValue(WidgetType.Sprocket, out widget2))
{
// do stuff
}
}
}
That's using Dependency Injection approach, if you just want to resolve the factory:
var factory = Container.Resolve<IIndex<WidgetType,Widget>>();

Categories

Resources