I'm using AutoFixture and I'd like to use a specific constructor.
I have the following code and I like to select the constructor with ITemplateParameterHandler.
public sealed class TemplateSegmentHandler : ITemplateSegmentHandler
{
public TemplateSegmentHandler(ITemplateIterator iterator)
: this(new TemplateParameterHandler(iterator))
{
Contract.Requires(iterator != null);
}
public TemplateSegmentHandler(ITemplateParameterHandler parameterHandler)
{
Contract.Requires(parameterHandler != null);
_parameterHandler = parameterHandler;
_parameterHandler.Ending += EndingParameter;
}
// ...
}
EDIT:
I want to inject the following fake implementation. (I'm using NSubstitute to create the fake object.)
public sealed class CustomTemplateParameter : ICustomization
{
private readonly ITemplateParameterHandler _context;
public CustomTemplateParameter()
{
_context = Substitute.For<ITemplateParameterHandler>();
}
public void Customize(IFixture fixture)
{
fixture.Customize<ITemplateParameterHandler>(c => c.FromFactory(() => _context));
}
public CustomTemplateParameter SetCatchAll(bool isCatchAll)
{
_context.IsCatchAll.Returns(isCatchAll);
return this;
}
}
Here is the way I'm trying to use it.
[Fact]
public void Should_return_true_when_the_segment_has_a_catch_all_parameter()
{
TemplateSegmentHandler segmentHandler = new Fixture().Customize(new TemplateSegmentHandlerFixture())
.Customize(new CustomTemplateParameterHandler()
.SetCatchAll(true))
.Create<TemplateSegmentHandler>();
segmentHandler.Parameter.Start();
segmentHandler.Parameter.End();
segmentHandler.HasCatchAll.Should().BeTrue();
}
But it still selects the wrong constructor and I'm getting the following error.
Ploeh.AutoFixture.ObjectCreationExceptionAutoFixture was unable to create an instance from Somia.Web.Routing.Template.ITemplateIterator, most likely because it has no public constructor, is an abstract or non-public type.
Request path:
Somia.Web.Routing.Template.TemplateSegmentHandler -->
Somia.Web.Routing.Template.ITemplateIterator iterator -->
Somia.Web.Routing.Template.ITemplateIterator
I ended up implementing IMethodQuery and select the ctor I wanted.
public sealed class SelectedFirstConstructorQuery : IMethodQuery
{
private readonly Type _type;
public SelectedFirstConstructorQuery(Type type)
{
_type = type;
}
public IEnumerable<IMethod> SelectMethods(Type type)
{
if (type == null)
{
throw new ArgumentNullException("type");
}
return from ci in type.GetConstructors()
let parameter = ci.GetParameters().First()
where parameter.ParameterType == _type
select new ConstructorMethod(ci) as IMethod;
}
}
Usage:
fixture.Customize<TemplateSegmentHandler>(c => c.FromFactory(new MethodInvoker(new SelectedFirstConstructorQuery(typeof(ITemplateParameterHandler)))));
One possible way:
var parameterHandler = fixture.Create<ITemplateParameterHandler>();
var segmentHandler = fixture.Build<TemplateSegmentHandler>()
.FromFactory(() => new TemplateSegmentHandler(parameterHandler));
fixture.Inject(segmentHandler);
Related
Is it possible to register same interface twice, where the first resolves to a default implementation and the second has a name and resolves to another type.
Example:
container.RegisterType(typeof(IMyInterface), typeof(MyDefaultImplementation));
container.RegisterType(typeof(IMyInterface), typeof(MySecondImplementation),"Second Implementations name");
So,
Resolve<IMyInterface>("non existing name")
Should resolve MyDefaultImplementation.
If you're OK with using the container you can do an extension method:
public static class UnityExtensions
{
public static T TryResolve<T>(this IUnityContainer container, string name)
{
if (container.IsRegistered<T>(name))
return container.Resolve<T>(name);
return container.Resolve<T>();
}
}
And use it like:
container.RegisterType<IMyInterface, Foo>();
container.RegisterType<IMyInterface, Bar>("bar");
var foo = container.TryResolve<IMyInterface>("non-existing");
// foo will be Foo
var bar = container.TryResolve<IMyInterface>("bar");
// bar will be Bar.
public interface IMyInterface { }
public class Foo : IMyInterface { }
public class Bar : IMyInterface { }
The downside is that you'll need to know when to use the extension and when not to... Otherwise you can build your own BuilderStrategy.
Heavily influensed by:
Unity - loadConfiguration, how to resolve only those configured
Is there TryResolve in Unity?
I'm not familiar enough with unity, but you cat start with creating you own configuration, add it as extension:
public class DefaultRegistrationFallbackConfiguration : UnityContainerExtension
{
protected override void Initialize()
{
this.Context.Registering += this.AppendRemapPolicy;
}
public override void Remove()
{
this.Context.Registering -= this.AppendRemapPolicy;
}
private void AppendRemapPolicy(object sender, RegisterEventArgs e)
{
if (e.Name != null)
return;
if (e.TypeFrom != null && e.TypeTo != null)
this.Context.Policies.SetDefault<IBuildKeyMappingPolicy>(new MapBuildKeyToDefaultPolicy(e.TypeFrom, e.TypeTo));
if (e.LifetimeManager == null)
return;
throw new NotImplementedException("TODO: lifetime management");
}
}
Create your own IBuildKeyMappingPolicy:
public class MapBuildKeyToDefaultPolicy : IBuildKeyMappingPolicy
{
private readonly Type _typeFrom;
private readonly Type _typeTo;
public MapBuildKeyToDefaultPolicy(Type typeFrom, Type typeTo)
{
this._typeFrom = typeFrom;
this._typeTo = typeTo;
}
public NamedTypeBuildKey Map(NamedTypeBuildKey buildKey, IBuilderContext context)
{
if (buildKey.Type == this._typeFrom)
return new NamedTypeBuildKey(this._typeTo);
throw new InvalidOperationException();
}
}
Test classes:
public interface IFoo
{
void Bar();
}
public class FooNamed : IFoo
{
public void Bar()
{
Console.WriteLine("named one");
}
}
public class FooDefault : IFoo
{
public void Bar()
{
Console.WriteLine("default one");
}
}
Test:
public static class Program
{
static void Main(string[] args)
{
var container = new UnityContainer();
// register extension before use container!
container.AddExtension(new DefaultRegistrationFallbackConfiguration());
container.RegisterType(typeof(IFoo), typeof(FooDefault));
container.RegisterType(typeof(IFoo), typeof(FooNamed), "named");
container.Resolve<IFoo>() .Bar(); // default one
container.Resolve<IFoo>("named") .Bar(); // named one
container.Resolve<IFoo>("unknown").Bar(); // default one
}
}
Output:
default one
named one
default one
I have several classes that take a dependency of type ILogger. The implementation of ILogger needs to know the type for which it is the logger, i.e. the ILogger for Foo will be new Logger(typeof(Foo)), for Bar it will be new Logger(typeof(Bar)), etc.
I would like the proper logger to be injected automatically by Unity; in other words, when I call container.Resolve<Foo>(), I want a new Logger(typeof(Foo)) to be injected into the Foo instance.
How can I set this up in Unity? Is there a way to pass the type being resolved to the dependency?
(In my real code, I actually have a ILoggerFactory with a Create method, which also takes a type as a parameter. So I could just pass the factory to my classes, and they would call Create themselves to get the appropriate logger, but it's not as elegant as what I'd like to achieve)
Some code to make things clearer:
interface ILogger
{
...
}
class Logger : ILogger
{
private readonly Type _type;
public Logger(Type type)
{
_type = type;
}
...
}
class Foo
{
private readonly ILogger _logger;
public Foo(ILogger logger) // here I want a Logger with its type set to Foo
{
_logger = logger;
}
}
This related question shows exactly what I'm trying to do, and the accepted answer is exactly the kind of thing I'm looking for... but it's for NInject, not Unity.
Here's a container extension that will set the Type parameter of the Logger constructor to the Type that the ILogger is being injected into.
The transient IBuilderContext.Policies is used to store the type that the ILogger is being injected into.
Maybe it's more complicated than it needs to be but this seems to work
public class LoggerExtension : UnityContainerExtension
{
public static NamedTypeBuildKey LoggerBuildKey = new NamedTypeBuildKey<Logger>();
protected override void Initialize()
{
Context.Strategies.Add(new LoggerTrackingPolicy(), UnityBuildStage.TypeMapping);
Context.Strategies.Add(new LoggerBuildUpStrategy(), UnityBuildStage.PreCreation);
}
}
public class LoggerTrackingPolicy : BuilderStrategy
{
public LoggerTrackingPolicy()
{
}
public override void PreBuildUp(IBuilderContext context)
{
if (context.BuildKey.Type != typeof(Logger))
{
var loggerPolicy = context.Policies.Get<ILoggerPolicy>(LoggerExtension.LoggerBuildKey);
if (loggerPolicy == null)
{
loggerPolicy = new LoggerPolicy();
context.Policies.Set<ILoggerPolicy>(loggerPolicy, LoggerExtension.LoggerBuildKey);
}
loggerPolicy.Push(context.BuildKey.Type);
}
}
}
public class LoggerBuildUpStrategy : BuilderStrategy
{
public LoggerBuildUpStrategy()
{
}
public override void PreBuildUp(IBuilderContext context)
{
if (context.BuildKey.Type == typeof(Logger))
{
var policy = context.Policies.Get<ILoggerPolicy>(LoggerExtension.LoggerBuildKey);
Type type = policy.Peek();
if (type != null)
{
context.AddResolverOverrides(new ParameterOverride("type", new InjectionParameter(typeof(Type), type)));
}
}
}
public override void PostBuildUp(IBuilderContext context)
{
if (context.BuildKey.Type != typeof(Logger))
{
var policy = context.Policies.Get<ILoggerPolicy>(LoggerExtension.LoggerBuildKey);
policy.Pop();
}
}
}
public interface ILoggerPolicy : IBuilderPolicy
{
void Push(Type type);
Type Pop();
Type Peek();
}
public class LoggerPolicy : ILoggerPolicy
{
private Stack<Type> types = new Stack<Type>();
public void Push(Type type)
{
types.Push(type);
}
public Type Peek()
{
if (types.Count > 0)
{
return types.Peek();
}
return null;
}
public Type Pop()
{
if (types.Count > 0)
{
return types.Pop();
}
return null;
}
}
How it works is: when a type that is not a Logger is trying to be resolved then, during the TypeMapping stage (before any creation), the type is pushed on a stack. Later, before creation, if the type is a Logger then the type it is being injected into is peeked from the stack and that type used as a resolver override. After creation, if the type is not a Logger, it is popped from the stack.
And some code to make sure it's working (I added a Type property to the logger just to verify it's set properly):
class Program
{
static void Main(string[] args)
{
IUnityContainer container = new UnityContainer();
container.RegisterType<ILogger, Logger>();
container.AddNewExtension<LoggerExtension>();
var a = container.Resolve<A>();
var b = container.Resolve<B>();
var c = container.Resolve<C>();
var d = container.Resolve<D>();
var x = container.Resolve<X>();
}
}
public interface ILogger
{
Type Type { get; }
}
public class Logger : ILogger
{
private readonly Type _type;
public Logger(Type type)
{
_type = type;
}
public Type Type { get { return _type; } }
}
public class A
{
public A(ILogger logger)
{
System.Diagnostics.Debug.Assert(logger.Type == typeof(A));
}
}
public class B
{
public B(ILogger logger)
{
System.Diagnostics.Debug.Assert(logger.Type == typeof(B));
}
}
public class C
{
public C(A a, D d, B b, ILogger logger)
{
System.Diagnostics.Debug.Assert(logger.Type == typeof(C));
}
}
public class D
{
public D()
{
}
}
public class X
{
public X(Y y)
{
}
}
public class Y
{
public Y(ILogger logger)
{
System.Diagnostics.Debug.Assert(logger.Type == typeof(Y));
}
}
As #spotco suggested, I would also recommend generics. The unity registration would be done using "open generics" as shown here. This single registration gives you the ability to resolve any type in the generics parameter of Logger.
unityContainer.RegisterType(typeof(ILogger<>), typeof(Logger<>));
Using that registration, you can resolve the instance using constructor injection like this.
public class MyClass
{
public MyClass(ILogger<MyClass> logger) { ... }
}
More info here.
I have the following code:
public interface IMyActionFactory
{
AbstractAction<T> CreateAction<T>(MyActionParamBase paramBase = null)
where T : MyActionParamBase;
}
public sealed class MergeActionParam : MyActionParamBase
{
}
public class MergeTest
{
private readonly IMyActionFactory _actionFactory = new DefaultMyActionFactory();
[Theory]
[PropertyData("MergeWorksData")]
public void MergeWorks(/*params here*/)
{
var param = new MergeActionParam();
// populate param here
var sut = _actionFactory.CreateAction<MergeActionParam>(param);
sut.DoAction();
}
}
I am getting an error
"..Error 10 Using the generic type 'IMyActionFactory' requires 1
type arguments..."
Why does the compiler expect a type to be passed to my IMyActionFactory, since I have declared the interface without a T? As far as the method is concerned its the only one to expect the type. Am I missing something here?
How can I make it work without redefining the interface signature?
EDIT:
Feeling a bit embarassed here, because the quick code I put down and ran seperately in a standalone online c# compiler doesnt give any compilation errors. However, going back to my original solution (tens of projects altogether) the error is still there.. Maybe has something to do with the XUnit ?..not sure
public interface IMyActionFactory
{
AbstractAction<T> CreateAction<T>(MyActionParamBase paramBase = null)
where T : MyActionParamBase;
}
public interface IAction
{
void DoAction();
}
public abstract class AbstractAction<T> : IAction
where T : MyActionParamBase
{
public void DoAction()
{
}
}
public class MyActionParamBase
{
public MyActionParamBase()
{
}
}
public sealed class MergeActionParam : MyActionParamBase
{
}
public class DefaultMyActionFactory : IMyActionFactory
{
public AbstractAction<T> CreateAction<T>(MyActionParamBase paramBase = null) where T : MyActionParamBase
{
return null;
}
}
public class MergeTest
{
private readonly IMyActionFactory _actionFactory = new DefaultMyActionFactory();
public void MergeWorks(/*params here*/)
{
var param = new MergeActionParam();
// populate param here
var sut = _actionFactory.CreateAction<MergeActionParam>(param);
sut.DoAction();
}
}
I was just working on some application architecture and this may sound like a stupid question but please explain to me how the following works:
Interface:
public interface IMatterDAL
{
IEnumerable<Matter> GetMattersByCode(string input);
IEnumerable<Matter> GetMattersBySearch(string input);
}
Class:
public class MatterDAL : IMatterDAL
{
private readonly Database _db;
public MatterDAL(Database db)
{
_db = db;
LoadAll(); //Private Method
}
public virtual IEnumerable<Matter> GetMattersBySearch(string input)
{
//CODE
return result;
}
public virtual IEnumerable<Matter> GetMattersByCode(string input)
{
//CODE
return results;
}
Controller:
public class MatterController : ApiController
{
private readonly IMatterDAL _publishedData;
public MatterController(IMatterDAL publishedData)
{
_publishedData = publishedData;
}
[ValidateInput(false)]
public JsonResult SearchByCode(string id)
{
var searchText = id; //better name for this
var results = _publishedData.GetMattersBySearch(searchText).Select(
matter =>
new
{
MatterCode = matter.Code,
MatterName = matter.Name,
matter.ClientCode,
matter.ClientName
});
return Json(results);
}
This works, when I call my controller method from jquery and step into it, the call to the _publishedData method, goes into the class MatterDAL.
I want to know how does my controller know to go to the MatterDAL implementation of the Interface IMatterDAL. What if I have another class called MatterDAL2 which is based on the interface. How will my controller know then to call the right method?
I am sorry if this is a stupid question, this is baffling me.
EDIT:
Based on the responses, it seems like this is where the dependency is being resolved:
This is a ninject call:
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<ICpdMatterDAL>().To<CachedCpdData>();
}
Where CachedCpdData is:
public class CachedCpdData : ICpdMatterDAL
{
private static readonly object CacheLockObject = new object();
private readonly MatterDAL _matterData;
public CachedCpdData()
{
_matterData = DomainModel.DataAccessManager.Instance.Matters;
}
public IEnumerable<Matter> GetMattersForAutoCompleteByCode(string input)
{
var cacheKey = string.Format("matter-search-{0}", input ?? "");
var result = HttpRuntime.Cache[cacheKey] as IEnumerable<Matter>;
if (result == null)
{
lock (CacheLockObject)
{
result = HttpRuntime.Cache[cacheKey] as IEnumerable<Matter>;
if (result == null)
{
result = _matterData.GetMattersForAutoCompleteByCode(input).ToList();
HttpRuntime.Cache.Insert(cacheKey, result, null, DateTime.Now.AddSeconds(60), TimeSpan.Zero);
}
}
}
return result;
}
public IEnumerable<Matter> GetMattersByMatterCodeSearch(string input)
{
return _matterData.GetMattersByMatterCodeSearch(input);
}
}
The rason why your code is using the right implementation of IMatterDAL is because it's being passed as a parameter in the constructor of MatterController. I'm almost sure that your code is using some Dependency Injection framework to resolve IMatterDAL.
In fact Ninject is a DI Framework. Your code should have something like
kernel.Bind<IMatterDAL>().To<MatterDAL >();
We're using domain to customize how our application behaves. I'll illustrate it on example:
// default behavior
public class CoreService : IService {
public virtual string Hello { get { return "Hello"; } }
public virtual string FavouriteDrink { get { return "Water"; } }
}
// german.site.com
public class GermanService : CoreService {
public override string Hello { get { return "Gutten tag"; } }
public override string FavouriteDrink { get { return "Beer"; } }
}
// usa.site.com
public class UsaService : CoreService {
public override string FavouriteDrink { get { return "Cofee"; } }
}
Services are bootstrapped as follow:
var container = new UnityContainer();
container.RegisterType<IService, CoreService>();
container.RegisterType<IService, GermanService>("german.site.com");
container.RegisterType<IService, UsaService>("usa.site.com");
I use Unity to bootstrap mvc controllers. IE:
public class HomeController : Controller {
private IService m_Service;
// contructor dependency injection magic - this resolves into "CoreService"
public HomeController([Dependency]IService service) {
if (service == null) {
throw new ArgumentNullException("service");
}
m_Service = service;
}
}
Is there a way how to change unity resolution so it'll take domain into account ? Right now I ended up with
public class HomeController : Controller {
private IService m_Service;
// contructor dependency injection magic - a lot less magical
public HomeController() {
m_Service = DomainServiceLocator.Retrieve<IService>();
}
}
Support classes:
public static class DomainServiceLocator {
private static UnityContainerAdapter adapter;
public static T Retrieve<T>() {
string domain = HttpContext.Current.Request.Url.Host;
if (adapter.IsServiceRegistered(typeof(T), domain)) {
return adapter.Resolve<T>(domain);
}
return adapter.Resolve<T>();
}
}
public class QueryableContainerExtension : UnityContainerExtension {
private List<RegisterInstanceEventArgs> registeredInstances = new List<RegisterInstanceEventArgs>();
private List<RegisterEventArgs> registeredTypes = new List<RegisterEventArgs>();
protected override void Initialize() {
this.Context.Registering += (sender, e) => { this.registeredTypes.Add(e); };
this.Context.RegisteringInstance += (sender, e) => { this.registeredInstances.Add(e); };
}
public bool IsServiceRegistered(Type service, string name) {
return registeredTypes.FirstOrDefault(e => e.TypeFrom == service && e.Name == name) != null
|| registeredInstances.FirstOrDefault(e => e.RegisteredType == service && e.Name == name) != null;
}
}
public class UnityContainerAdapter {
private readonly QueryableContainerExtension queryableContainerExtension;
private readonly IUnityContainer unityContainer;
public UnityContainerAdapter()
: this(new UnityContainer()) {
}
public UnityContainerAdapter(IUnityContainer unityContainer) {
this.unityContainer = unityContainer;
// adding extensions to unity container
this.queryableContainerExtension = new QueryableContainerExtension();
unityContainer.AddExtension(this.queryableContainerExtension);
}
public T Resolve<T>(string name) {
return unityContainer.Resolve<T>(name);
}
public T Resolve<T>() {
return unityContainer.Resolve<T>();
}
public bool IsServiceRegistered(Type service, string name) {
return this.queryableContainerExtension.IsServiceRegistered(service, name);
}
}
I like to use an injection factory in these scenarios when resolving something at runtime. Essentially you're resolving your type via the domain name:
So in your composition root you could register like this:
container.RegisterType<Func<string, IService>>
(
new InjectionFactory(c => new Func<string, IService>(name => c.Resolve<IService>(name)))
);
Then in your HomeController you can inject the delegate
public class HomeController
{
private readonly Func<string,IService> _serviceFactory;
public HomeController(Func<string, IService> serviceFactory)
{
if(serviceFactory==null)
throw new ArgumentNullException("serviceFactory");
this._serviceFactory= serviceFactory;
}
public void DoSomethingWithTheService()
{
var domain = this.HttpContext.Uri.Host;
var service = this._serviceFactory(domain);
var greeting = service.Hello;
}
}
```
This is then still unit testable and you have not leaked the DI contain implementation outside of "composition root".
Also.. should CoreService be abstract to avoid direct instantiation of it?
Below is the solution I ended up with - it is based on #Spencer idea. I've created a factory, default implementation to the factory has a reference to DI container itself (IUnityContainer in my case), so it can perform the resolution based on domain once it is asked to. It is also more "modern friendly" since in current generation of ASP.NET (ASP.NET CORE) there is no such thing as magic singleton providing current HttpContext and DI is hard coded into the framework.
public interface IFactory<T>
{
T Retrieve(string domain);
}
internal sealed class Factory<T> : IFactory<T>
{
private readonly IUnityContainer _container;
public Factory(IUnityContainer container)
{
_container = container;
}
public T Resolve(string domain)
{
// this is actually more complex - we have chain inheritance here
// for simplicity assume service is either registered for given
// domain or it throws an error
return _container.Resolve<T>(domain);
}
}
// bootstrapper
var container = new UnityContainer();
container.RegisterType<IService, CoreService>();
container.RegisterType<IService, GermanService>("german.site.com");
container.RegisterType<IService, UsaService>("usa.site.com");
container.RegisterInstance<IFactory<IService>>(new Factory<IService>(container));
And the home controller looks like
public class HomeController : Controller {
private IFactory<IService> m_Factory;
public HomeController(IFactory<IService> factory) {
m_Factory = factory;
}
private void FooBar() {
var service = m_Factory.Retrieve(this.HttpContext.Uri.Host);
var hello = service.Hello;
}
}
Its also a worth mentioning that - as I'm lazy - I've build a system of decorative attributes like
[Domain("german.site.com")]
public class GermanService : IService { ... }
[DomainRoot]
public class CoreService : IService { ... }
[Domain("usa.site.com")]
public class UsaService : CoreService { ... }
So the bootstrapping is done automatically across all types in given assembly. But that part is a bit lengthy - if anyone is interested I can post it on github.