use named mapping type to resolve constructor parameter with Unity - inversion-of-control

I want to garanty that unity resolve a constructor parameter using a named registration, for example:
I have two type registrations:
_container.RegisterType<IMyInterface, Implementation1>("implementation1");
_container.RegisterType<IMyInterface, Implementation2>("implementation2");
When unity resolve a class with the following contructor:
public class Example
{
Example(IMyInterface args)
{
}
}
How should i specify to unity that must resolve using "implementation2" in this case only

You can configure a type registration in Unity to resolve a constructor argument to a specific named type using the following:
container.RegisterType<IExample, Example>(
new InjectionConstructor(new ResolvedParameter<IMyInterface>("implementation2")));

Related

Is there a way to fix the warning related to the support of string-based lookup for the factory?

I often get this warning message:
UVM_WARNING # 0: reporter [TPRGED] Type name 'packet2mem_comp_Str' already registered with factory. No string-based lookup support for multiple types with the same type name.
I did not register any class with the same name, unless the parent one which, I suppose, does not present any problem.
My class is an inherited parametrized class declared as follows:
class packet2mem_comp #(string S = "MEM") extends mem_comp;
typedef packet2mem_comp #(S) packet2mem_comp_Str;
`uvm_object_utils(packet2mem_comp_Str)
function new (string name = "packet2mem_comp");
super.new(name);
endfunction : new
... //rest of my code
endclass: packet2mem_comp
Does anyone know how to fix this warning?
There are special versions of the macros for parameterised classes. Instead of
`uvm_object_utils(packet2mem_comp_Str)
try
`uvm_object_param_utils(packet2mem_comp_Str)
or perhaps
`uvm_object_param_utils(packet2mem_comp #(S))
You have not posted an MCVE, so I have not tested this.

Registering a type with both EnableClassInterceptors and WithParameter

I'm having an issue with Autofac where it seems like EnableClassInterceptors is interfering with my ability to use .WithParameter(...). When the constructor is being called on Service using the code below, someString is not being populated. Notes:
I've tried using ResolvedParameter instead, it does not help (note: my Resolved parameter still includes the name of the parameter when I tried that)
If I remove EnableClassInterceptors and InterceptedBy, the parameter does get populated properly. This, however, isn't a valid solution as I need the interceptors.
Re-ordering WithParameter, EnableClassInterceptors, and InterceptedBy does not help.
Looking at Type Interceptors, specifically the "Class Interceptors and UsingConstructor" section, on docs.autofac.org, it mentions that using EnableClassInterceptors will cause ConstructUsing to fail. I think something similar might be happening with my scenario below.
Snippet of my registration code looks like this:
var builder = new ContainerBuilder();
builder.RegisterType<Dependency>.As<IDependency>.InstancePerLifetimeScope();
builder.RegisterType<Service>()
.As<IService>()
.WithParameter(new NamedParameter("someString", "TEST"))
.EnableClassInterceptors()
.InterceptedBy(typeof(LogExceptionsInterceptor));
Service's constructor looks something like this:
public class Service : IService
{
public Service(IDependency dependency, string someString)
{
if(dependency == null)
throw ArgumentNullException(nameof(dependency));
if(someString == null)
//**throws here**
throw ArgumentNullException(nameof(someString));
}
}
[Guess] What I'm thinking is happening is that when EnableClassInterceptors is called, a proxy class is generated with a constructor that works on top of the existing one, but the parameter names do not copy over into the proxy class/constructor.
Is this a problem? Is there a way to form the registration that allows both WithParameter and EnableClassInterceptors to be used together? Is it a bug in Autofac?
Your guess is correct: the generated proxy class does not keep the constructor parameter names.
Currently there is no way to influence this in DynamicProxy so this is not a bug of Autofac (although this edge case currently not documented on the Autofac documentation website).
This is how your original Service class's parameters look like:
typeof(Service).GetConstructors()[0].GetParameters()
{System.Reflection.ParameterInfo[2]}
[0]: {ConsoleApplication10.IDependency dependency}
[1]: {System.String someString}
But the generated proxy does not keep the names:
GetType().GetConstructors()[0].GetParameters()
{System.Reflection.ParameterInfo[3]}
[0]: {Castle.DynamicProxy.IInterceptor[] }
[1]: {ConsoleApplication10.IDependency }
[2]: {System.String }
So you have two not very robust options to workaround this limitation with WithParameter:
use the TypedParamter with string as the type:
.WithParameter(new TypedParameter(typeof(string), "TEST"))
However if you have multiple paramters with the same type this won't work
use the PositionalParameter in this case you need to add 1 if the type is proxied
.WithParameter(new PositionalParameter(2, "TEST"))
Another options would be to don't use a primitive string type but create a wrapper e.g. MyServiceParameter or create another service which can provide these string configuration values to your other services.

How do I register an interface to the EntityFramework.UserStore<TUser> constructor?

I have been following this post to learn about DI with AutoFac. My DB context is registered in Startup.cs like this:
builder.RegisterType<MyDb>().As<IMyDbCtx>().InstancePerRequest();
I also followed the instructions to create the ApplicationUserStore class, and registered this type like so:
builder.RegisterType<ApplicationUserStore>().As<IUserStore<ApplicationUser>>().InstancePerRequest();
This was all fine until I realized that ApplicationUserStore is expecting a concrete DbContext in it's constructor to pass to its base constructor:
public ApplicationUserStore(MyDb context)
: base(context)
{
}
When I run the application and try loading the registration page, this is the error I see:
None of the constructors found with 'Autofac.Core.Activators.Reflection.DefaultConstructorFinder' on type 'TestApp.Service.IdentityConfig.ApplicationUserStore' can be invoked with the available services and parameters:
Cannot resolve parameter 'TestApp.Data.MyDb context' of constructor 'Void .ctor(MyApp.Data.MyDb)'.
This is breaking, I assume, because I already set up MyDb as a IMyDbCtx, so it won't accept the concrete type. This is good because I don't want to be inconsistent by injecting abstractions in some spots and implementations in others.
Does anyone have any ideas on how I can pass in an IMyDbCtx to the UserStore ctor, particularly with AutoFac?
This is not an ideal solution, but I decided to cast the interface to the concrete type when the parameter is passed to the base constructor:
public ApplicationUserStore(IMyDbCtx context)
: base((MyDb)context)
{
}
You can register your type MyDb under as many aliases as you wish:
builder.RegisterType<MyDb>()
.As<MyDb>()
.As<IMyDbCtx>()
.InstancePerRequest();
In this case Autofac can resolve Application User Store. But it kills the whole idea of dependency injection, because you feed the concrete type.

Extbase Repository objectType = NULL

We are migrating a 4.5 Extension to 7.2. One special case is strange. Trying to get a findOneByUid brings a "No class name was given to retrieve the Data Map for." Error.
Accessing via another object and using the DebuggerUtility it allows us to navigate to the object that fails, and there we can see, the objectType is NULL.
Any clue where to search? All the other objects can be accessed via findOneByUid.
How would you proceed to find the issue?
Adding the following lines solved the problem... any idea how to avoid this?
public function __construct() {
$this->objectManager = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Extbase\\Object\\ObjectManager');
$this->objectType = \TYPO3\CMS\Core\Utility\ClassNamingUtility::translateRepositoryNameToModelName($this->getRepositoryClassName());
}
The object type can only be null if the constructor of the repository has been overridden in a subclass without a call to the parent constructor. parent::__construct();
Instead of using the constructor, you should make use of the method initializeObject, which gets called after the constructor and which can safely be overridden.

Resolving constructor paramters using the same name used for resolving the object

Say I have this class
public class MyObject : IObject
{
public MyObject(IObject2 object2)
{
}
}
which I resolve like:
Container.Resolve<IObject>("SomeName");
Is it possible to configure Unity so that whenever an IObject is resolved using any name, then the IObject2 will also be resolved with that same name (assuming it was registered with such a name)?
I'm looking for a way that doesn't use InjectionConstructor, as I son't want to update it for every new name I introduce.
This ought to work:
container.RegisterType<IObject2, MyObject2>("someName");
// ...
container.RegisterType<IObject, MyObject>("someName",
new InjectionConstructor(
new ResolvedParameter<IObject2>("someName")));
If you want to register more names, you could always consider packaging this little snippet into a reusable method that takes the name as an input parameter.
I don't have Unity nearby right now, so this is more or less from memory...