Autofac: Resolve a specific dependency to a named instance - ioc-container

Using Autofac, I would like to register a component and specify for a specific dependency to be resolved to a named instance.
I found samples like the following using constructor injection which is almost what I want.
builder.Register(c => new ObjectContainer(ConnectionStrings.CustomerDB))
.As<IObjectContainer>()
.Named("CustomerObjectContainer");
builder.Register(c => new ObjectContainer(ConnectionStrings.FooDB))
.As<IObjectContainer>()
.Named("FooObjectContainer");
builder.Register(c => new CustomerRepository(
c.Resolve<IObjectContainer>("CustomerObjectContainer"));
builder.Register(c => new FooRepository(
c.Resolve<IObjectContainer>("FooObjectContainer"));
However, I need this with property injection and I don't want to specify all dependencies.
Something like:
builder.Register<CustomerRepository>().With<IObjectContainer>("CustomerObjectContainer");
builder.Register<FooRepository>().With<IObjectContainer>("FooObjectContainer");
The build up of all unspecified dependnecies should happen with unnamed instances.
Thanks,
Alex
[ADDITION TO THE ANSWER FROM Danielg]
An overload to resolve by type for any property of that type.
public static IRegistrationBuilder<TLimit, TReflectionActivatorData, TStyle> WithDependency<TLimit, TReflectionActivatorData, TStyle, TProperty>(
this IRegistrationBuilder<TLimit, TReflectionActivatorData, TStyle> registration,
Func<IComponentContext, TProperty> valueProvider)
where TReflectionActivatorData : ReflectionActivatorData
{
return registration.WithProperty(new ResolvedParameter((p, c) =>
{
PropertyInfo prop;
return p.TryGetDeclaringProperty(out prop) &&
prop.PropertyType == typeof(TProperty);
},
(p, c) => valueProvider(c)));
}

I don't think that autofac has a shorthand way of doing this yet, but it is possible with a little effort.
I've written an extension method that does this. Throw it in a static extension class and you should be fine. The extension also shows how to do this the long way.
public static IRegistrationBuilder<TLimit, TReflectionActivatorData, TStyle> WithResolvedProperty<TLimit, TReflectionActivatorData, TStyle, TProperty>(
this IRegistrationBuilder<TLimit, TReflectionActivatorData, TStyle> registration,
string propertyName, Func<IComponentContext, TProperty> valueProvider)
where TReflectionActivatorData : ReflectionActivatorData
{
return registration.WithProperty(new ResolvedParameter((p, c) =>
{
PropertyInfo prop;
return p.TryGetDeclaringProperty(out prop) &&
prop.Name == propertyName;
},
(p, c) => valueProvider(c)));
}
Don't mind the super long method signature, autofac registrations are very verbose.
You can use the extension like this.
builder.RegisterType<Foo>()
.WithResolvedProperty("Bar", c => c.Resolve<IBar>());

Related

How do I bind an Interface to automapper using Ninject

I want to use DI whenever I call automapper so that I can uncouple some of my layers. Instead of calling automapper like this:
public class MyController : Controller
{
public ActionResult MyAction(MyModel model)
{
var newModel= Mapper.Map<MyModel, NewModel>(model);
return View(model);
}
}
I want to do this:
public class MyController : Controller
{
IMappingEngine _mappingEngine;
public MyController(IMappingEngine mappingEngine)
{
_mappingEngine = mappingEngine;
}
public ActionResult MyAction(MyModel model)
{
var newModel= _mappingEngine.Map<MyModel, NewModel>(model);
return View(model);
}
}
I am using Ninject as my IOC. How do I bind an interface to it though?
I also need to mention that I am using Profiles and already have:
var profileType = typeof(Profile);
// Get an instance of each Profile in the executing assembly.
var profiles = Assembly.GetExecutingAssembly().GetTypes()
.Where(t => profileType.IsAssignableFrom(t)
&& t.GetConstructor(Type.EmptyTypes) != null)
.Select(Activator.CreateInstance)
.Cast<Profile>();
// Initialize AutoMapper with each instance of the profiles found.
Mapper.Initialize(a => profiles.ForEach(a.AddProfile));
I know that the step I am missing involves binding to the kernal:
kernel.Bind<IMappingEngine>.To<>(); //I do not know what
//to bind it to here so that when I call IMappingEngine;
//It will trigger my maps from my automapper profiles.
I can't seem to find IMappingService in the AutoMapper repository (https://github.com/AutoMapper/AutoMapper/search?q=IMappingService). However, there is a IMappingEngine.
All you've got to do is
IBindingRoot.Bind<IMappingEngine>().ToMethod(x => Mapper.Engine);
or
IBindingRoot.Bind<IMappingEngine>().To<MappingEngine>();
IBindingRoot.Bind<IConfigurationProvider>().ToMethod(x => Mapper.Engine.ConfigurationProvider);
and you're good to go.
Remember, however, that the first access to Mapper.Engine or Mapper.ConfigurationProvider will initialize AutoMapper.
So without the binding, AutoMapper get's initialized the first time you do something like Mapper.Map<,>. With the binding it will get initialized the first time an object is constructed which gets IMappingEngine injected.
If you want to retain the previous initialization behavior there are a few choices:.
a) Instead of injecting IMappingEngine inject Lazy<IMappingEngine> instead (i think this requires the ninject.extensions.factory extension)
b) bind IMappingEngine to a proxy (without target). The proxy should access the Mapper.Engine only when .Intercept(...)ing a method. Also it should forward the method calls.
c) write your own LazyInitializedMappingEngine : IMappingEngine implementation which does nothing than forward every method to Mapper.Engine.
i would probably go with c), the others are too much work. c) will require code adaption whenever the interface of IMappingEngine changes. b) would not but is more complicated and slower. a) is bleeding through to all consumers of the interface and easily to get wrong once in a while, breaking stuff and a bit hard to trace back, so i would refrain from it, too.
c):
public class LazyInitializedMappingEngine : IMappingEngine
{
public IConfigurationProvider ConfigurationProvider { get { return Mapper.Engine.ConfigurationProvider; } }
public TDestination Map<TDestination>(object source)
{
return Mapper.Map<TDestination>(source);
}
public TDestination Map<TDestination>(object source, Action<IMappingOperationOptions> opts)
{
return Mapper.Map<TDestination>(source, opts);
}
public TDestination Map<TSource, TDestination>(TSource source)
{
return Mapper.Map<TSource, TDestination>(source);
}
//... and so on ...
}
kernel.Bind<IMappingEngine>().To<LazyInitializedMappingEngine>();

DbContext API Ignore for each entity

I’m trying to use CodeFirst EF. The issue is it's loading 50+ tables for each domain context (DbContext). The ignore is working if I pass the strong name class so the compiler knows what it is but it will be too hard to hardcode all the ignores.
Is there a way to loop through all the classes in a referenced DLL and pass that to the ignore? I have code that is close (taking code from post) but I can’t figure out a way to pass the class type with Assembly information. I’m so close yet so far away…
Assembly pocoQMAssembly = AssemblyInformationPOCO_QM.Get;
foreach (Type typeInfo in pocoQMAssembly.GetTypes())
{
//Make sure it is not one of the classes used in DbSet<>
if (typeInfo != typeof(tbl_age_groups) ||
typeInfo != typeof(tbl_axis)
)
{
//This line will show an error on typeInfo
//Is there a way to cast it to a class in some way so it likes it?
modelBuilder.Ignore<typeInfo>();
}
}
This will expose the Assembly to get it easily.
public class AssemblyInformationPOCO_QM
{
public static System.Reflection.Assembly Get
{
get
{
return typeof(AssemblyInformationPOCO_QM).Assembly;
}
}
}
Here is some code that does what you are after. It finds all types that are explicitly included in a DbSet property, it then uses this to find all types in your model assembly that aren't in a DbSet, and then calls Ignore on them.
public class MyContext : DbContext
{
// DbSet properties go here
protected override void OnModelCreating(DbModelBuilder modelBuilder)
{
var dbSetTypes = this.GetType()
.GetProperties()
.Where(p => p.PropertyType.Name == "DbSet`1")
.Select(s => s.PropertyType.GenericTypeArguments.Single());
var nonDbSetTypes = typeof(MyEntityClass).Assembly // <- replace MyEntityClass with one of your types
.GetTypes()
.Except(dbSetTypes);
modelBuilder.Ignore(nonDbSetTypes);
}
}

Ninject Get<T> WhenTargetHas<T>

So I'm using Ninject, specifically the contextual binding as follows :
Bind<IBlah>().ToMethod(x => FirstBlahProvider.Instance.GiveMeOne()).WhenTargetHas<FirstAttribute>().InRequestScope();
Bind<IBlah>().ToMethod(x => SecondBlahProvider.Instance.GiveMeOne()).WhenTargetHas<SecondAttribute>().InRequestScope();
I need to use the Kernel to get a given instance and would like to do it based on the Condition WhenTargetHas<T>. Something like the following would be great.
var myblah = Kernal.Get<IBlah>(x => x.HasWithTarget<FirstAttribute>)
How can you retrieve an instance based on the condition?
Worked out the answer :
Best to avoid using WhenTargetHas<T> instead use WithMetaData(key, value)
So
Bind<IBlah>().ToMethod(x => FirstBlahProvider.Instance.GiveMeOne()).WhenTargetHas<FirstAttribute>().InRequestScope();
Bind<IBlah>().ToMethod(x => SecondBlahProvider.Instance.GiveMeOne()).WhenTargetHas<SecondAttribute>().InRequestScope();
Becomes :
Bind<IBlah>().ToMethod(x => FirstBlahProvider.Instance.GiveMeOne()).WithMetaData("Provider", "First);
Bind<IBlah>().ToMethod(x => SecondBlahProvider.Instance.GiveMeOne()).WithMetaData("Provider", "Second");
You then need to create an Attribute which inherits the Ninject ConstraintAttribute and use that attribute in your constructor arguement.
As :
[AttributeUsage(AttributeTargets.Property | AttributeTargets.Field | AttributeTargets.Parameter, AllowMultiple = true, Inherited = true)]
public class FirstProviderConstraint : ConstraintAttribute
{
public override bool Matches(IBindingMetadata metadata)
{
return metadata.Has("Provider") && metadata.Get<string>("Provider") == "First";
}
}
You then use it in a constructor arg as :
public class Consumer([FirstProviderConstraint] IBlah)
{
...
}
Or resolving from the Kernel
Get<ISession>(metaData => metaData.Get<string>(BindingKeys.Database) == BindingValues.OperationsDatabase)
I need to resolve scoping but that's how you satisfy both Constructor injection and explicit resolution from the Kernel when you have more than one binding.

c++/cli delegates + lambda + overload funcions

I haven't any idea about how to do the same in c++/cli.
Is not clear for me how a I can create delegate and how I can invoke it.
Can someone help me?
Thanks.
public class Writer {
internal Dictionary<Type, Action<object>> Reflective = new Dictionary<Type, Action<object>>();
public Writer()
{
Reflective.Add(typeof(float), (value) => Write((float)value));
Reflective.Add(typeof(double), (value) => Write((double)value));
}
public void Write(float value)
{
Console.WriteLine("Float");
}
public void Write(double value)
{
Console.WriteLine("Double");
}
public void Write<T>(T[] values)
{
var method = this.Reflective[typeof(T)];
foreach (var value in values)
{
method(value);
}
}
}
I won't write the whole thing for you, but here's a couple of the non-obvious things to get you started:
typeof(float) ==> System::Single::typeid
// I like to specify the full namespace for explicitness.
Lambdas: C++/CLI does not support lambdas. You'll need to declare a full-fledged method, and construct a delegate to that. Fortunately, you already have that, your two Write methods should work. Don't forget when declaring the delegate, if it's an instance method, you'll need to specify the object to invoke the function on, which should be this in your code.

C# ‘dynamic’ cannot access properties from anonymous types declared in another assembly

Code below is working well as long as I have class ClassSameAssembly in same assembly as class Program.
But when I move class ClassSameAssembly to a separate assembly, a RuntimeBinderException (see below) is thrown.
Is it possible to resolve it?
using System;
namespace ConsoleApplication2
{
public static class ClassSameAssembly
{
public static dynamic GetValues()
{
return new
{
Name = "Michael", Age = 20
};
}
}
internal class Program
{
private static void Main(string[] args)
{
var d = ClassSameAssembly.GetValues();
Console.WriteLine("{0} is {1} years old", d.Name, d.Age);
}
}
}
Microsoft.CSharp.RuntimeBinder.RuntimeBinderException: 'object' does not contain a definition for 'Name'
at CallSite.Target(Closure , CallSite , Object )
at System.Dynamic.UpdateDelegates.UpdateAndExecute1[T0,TRet](CallSite site, T0 arg0)
at ConsoleApplication2.Program.Main(String[] args) in C:\temp\Projects\ConsoleApplication2\ConsoleApplication2\Program.cs:line 23
I believe the problem is that the anonymous type is generated as internal, so the binder doesn't really "know" about it as such.
Try using ExpandoObject instead:
public static dynamic GetValues()
{
dynamic expando = new ExpandoObject();
expando.Name = "Michael";
expando.Age = 20;
return expando;
}
I know that's somewhat ugly, but it's the best I can think of at the moment... I don't think you can even use an object initializer with it, because while it's strongly typed as ExpandoObject the compiler won't know what to do with "Name" and "Age". You may be able to do this:
dynamic expando = new ExpandoObject()
{
{ "Name", "Michael" },
{ "Age", 20 }
};
return expando;
but that's not much better...
You could potentially write an extension method to convert an anonymous type to an expando with the same contents via reflection. Then you could write:
return new { Name = "Michael", Age = 20 }.ToExpando();
That's pretty horrible though :(
You could use [assembly: InternalsVisibleTo("YourAssemblyName")] to make you assembly internals visible.
I ran into a similair problem and would like to add to Jon Skeets answer that there is another option. The reason I found out was that I realized that many extension methods in Asp MVC3 uses anonymous classes as input to provide html attributes (new {alt="Image alt", style="padding-top: 5px"} =>
Anyway - those functions use the constructor of the RouteValueDictionary class. I tried that myself, and sure enough it works - though only the first level (I used a multi-level structure). SO - in code this would be:
object o = new {
name = "theName",
props = new {
p1 = "prop1",
p2 = "prop2"
}
}
SeparateAssembly.TextFunc(o)
//In SeparateAssembly:
public void TextFunc(Object o) {
var rvd = new RouteValueDictionary(o);
//Does not work:
Console.WriteLine(o.name);
Console.WriteLine(o.props.p1);
//DOES work!
Console.WriteLine(rvd["name"]);
//Does not work
Console.WriteLine(rvd["props"].p1);
Console.WriteLine(rvd["props"]["p1"]);
SO... What is really going on here? A peek inside the RouteValueDictionary reveals this code (values ~= o above):
foreach (PropertyDescriptor descriptor in TypeDescriptor.GetProperties(values))
object obj2 = descriptor.GetValue(values);
//"this.Add" would of course need to be adapted
this.Add(descriptor.Name, obj2);
}
SO - using TypeDescriptor.GetProperties(o) we would be able to get the properties and values despite the anonymous type being constructed as internal in a separate assembly! And of course this would be quite easy to extend to make it recursive. And to make an extension method if you wanted.
Hope this helps!
/Victor
Here is a rudimentary version of an extension method for ToExpandoObject that I'm sure has room for polishing.
public static ExpandoObject ToExpandoObject(this object value)
{
// Throw is a helper in my project, replace with your own check(s)
Throw<ArgumentNullException>.If(value, Predicates.IsNull, "value");
var obj = new ExpandoObject() as IDictionary<string, object>;
foreach (var property in value.GetType().GetProperties(BindingFlags.Public | BindingFlags.Instance))
{
obj.Add(property.Name, property.GetValue(value, null));
}
return obj as ExpandoObject;
}
[TestCase(1, "str", 10.75, 9.000989, true)]
public void ToExpandoObjectTests(int int1, string str1, decimal dec1, double dbl1, bool bl1)
{
DateTime now = DateTime.Now;
dynamic value = new {Int = int1, String = str1, Decimal = dec1, Double = dbl1, Bool = bl1, Now = now}.ToExpandoObject();
Assert.AreEqual(int1, value.Int);
Assert.AreEqual(str1, value.String);
Assert.AreEqual(dec1, value.Decimal);
Assert.AreEqual(dbl1, value.Double);
Assert.AreEqual(bl1, value.Bool);
Assert.AreEqual(now, value.Now);
}
Below solution worked for me in my console application projects
Put this [assembly: InternalsVisibleTo("YourAssemblyName")]
in \Properties\AssemblyInfo.cs of the separate project with function returning dynamic object.
"YourAssemblyName" is the assembly name of calling project. You can get that through Assembly.GetExecutingAssembly().FullName by executing it in calling project.
A cleaner solution would be:
var d = ClassSameAssembly.GetValues().ToDynamic();
Which is now an ExpandoObject.
Remember to reference:
Microsoft.CSharp.dll
ToExpando extension method (mentioned in Jon's answer) for the brave ones
public static class ExtensionMethods
{
public static ExpandoObject ToExpando(this object obj)
{
IDictionary<string, object> expando = new ExpandoObject();
foreach (PropertyDescriptor propertyDescriptor in TypeDescriptor.GetProperties(obj))
{
var value = propertyDescriptor.GetValue(obj);
expando.Add(propertyDescriptor.Name, value == null || new[]
{
typeof (Enum),
typeof (String),
typeof (Char),
typeof (Guid),
typeof (Boolean),
typeof (Byte),
typeof (Int16),
typeof (Int32),
typeof (Int64),
typeof (Single),
typeof (Double),
typeof (Decimal),
typeof (SByte),
typeof (UInt16),
typeof (UInt32),
typeof (UInt64),
typeof (DateTime),
typeof (DateTimeOffset),
typeof (TimeSpan),
}.Any(oo => oo.IsInstanceOfType(value))
? value
: value.ToExpando());
}
return (ExpandoObject)expando;
}
}
If you're already using Newtonsoft.Json in your project (or you're willing to add it for this purpose), you could implement that horrible extension method Jon Skeet is referring to in his answer like this:
public static class ObjectExtensions
{
public static ExpandoObject ToExpando(this object obj)
=> JsonConvert.DeserializeObject<ExpandoObject>(JsonConvert.SerializeObject(obj));
}