property injection not working, help. Unity - c#

I spent a few hours trying to resolve this but with no luck. I'm using unity to inject my _translation property in my SSPResourceManagerWrapper Class which is returning back a null, instead of the translationService object.
Registering Dependency UIbootstrapper class gets called when the app starts to register all dependencies. And resolved when controller object is created.
public class UiBootstrapper
{
public static IUnityContainer RegisterUiComponents(IUnityContainer container)
{
container.RegisterType<SSPResourceManagerWrapper>();
container.RegisterType<SSPResourceManager>();
container.RegisterType<ITranslationService, TranslationService>();
return container;
}
_translation property returning null here. instead of translationService object
public class SSPResourceManager
{
private static ITranslationService _translationService;
private static string _languageCode =
System.Web.HttpContext.Current.Session["LanguageCode"].ToString();
// constructor injection
public SSPResourceManager(ITranslationService translationService)
{
_translationService = translationService;
}
public static string SSP_Validation_Required
{
get
{
return _translationService.Read("SSP_Validation_Required", "SSP", _languageCode);
}
}
}
Where SSPResourceManager is used
public abstract class AddressVM
{
[Required(ErrorMessageResourceType = typeof(SSPResourceManager), ErrorMessageResourceName
= "SSP_Validation_Required")]
[StringLength(50)]
public string Name { get; set; }
}

You are creating your own instance of SSPResourceManagerWrapper instead of resolving it using the Unity container:
private static ITranslationService _translationService =
new SSPResourceManagerWrapper()._translation;
The container never has the opportunity to supply the dependencies. Try using Resolve:
private static ITranslationService _translationService =
container.Resolve<SSPResourceManagerWrapper>()._translation;
or even better:
private static ITranslationService _translationService =
container.Resolve<ITranslationService>();

Related

How to make the ActivatorUtilities.CreateInstance method use a different constructor?

Is there a way the tell the ActivatorUtilities.CreateInstance<T>(IServiceProvider serviceProvider); method to try to use other constructors if the first one can't be constructed?
I have a class with multiple constructors:
public ViewModelB(SomeDependency someDependency): this one only takes SomeDependency which is registered in a DI container
public ViewModelB(SomeDependency someDependency, GetUserRequest request): this one takes SomeDependency which is registered in a DI container and a GetUserRequest which has to be passed in manually
And I'm trying to activate them and resolve dependencies like so:
IServiceProvider serviceProvider; //this gets passed from somewhere
Guid userId; //this gets passed manually by the caller
//works
var instanceAWithoutParams = ActivatorUtilities.CreateInstance<ViewModelA>(serviceProvider);
//works
var instanceAWithParams = ActivatorUtilities.CreateInstance<ViewModelA>(serviceProvider, new[] { new GetUserRequest { UserId = userId } });
//does NOT work, it tries to use the first constructor and fails
var instanceBWithoutParams = ActivatorUtilities.CreateInstance<ViewModelB>(serviceProvider);
//works
var instanceBWithParams = ActivatorUtilities.CreateInstance<ViewModelB>(serviceProvider,, new[] { new GetUserRequest { UserId = userId } });
The activation of instanceBWithoutParams fails because it can't resolve the request parameter. It tries to use the first constructor and doesn't check other ones when the activation fails.
Here's what the services look like, they're the same with one difference: the order of the constructors.
public class ViewModelA
{
private readonly SomeDependency _someDependency;
private readonly GetUserRequest? _request;
public ViewModelA(SomeDependency someDependency)
{
_someDependency = someDependency;
}
public ViewModelA(SomeDependency someDependency, GetUserRequest request)
{
_someDependency = someDependency;
_request = request;
}
}
public class ViewModelB
{
private readonly SomeDependency _someDependency;
private readonly GetUserRequest? _request;
public ViewModelB(SomeDependency someDependency, GetUserRequest request)
{
_someDependency = someDependency;
_request = request;
}
public ViewModelB(SomeDependency someDependency)
{
_someDependency = someDependency;
}
}
public class GetUserRequest
{
public Guid UserId { get; set; }
}
Thanks.
I struggled with the same issue. Eventually I came up with this solution:
I would use something like a factory which is able to construct ServiceB by calling a method.
For example:
var serviceBFactory = ActivatorUtilities.CreateInstance<ServiceBFactory>(serviceProvider);
var instanceBWithoutParams = serviceBFactory.CreateServiceB();
var instanceBWithParams = serviceBFactory.CreateServiceB(new Request());
This way you keep you DI clean. But this means that the ServiceBFactory need to know which services need to be injected in a ServiceB. (so that will be a tight coupling) They come as a package.
I've chosen to re-design the view models instead of trying to pass optional parameters next to services from DI (thanks to Steven for the helpful articles: 1 and 2).
There also seems to be no way of making the ActivatorUtilities.CreateInstance<T>(IServiceProvider serviceProvider); method try other constructors after one fails, so here's what my edited solution looks like.
I've moved the initialization of the optional parameter out of the constructor, that way I only have one constructor that only takes injectables. The parameter is then passed separately via the TakeParameter method. The only downside I can think of is that the parameter can no longer be readonly and I can live with that.
My custom activator utility:
public interface IAcceptParameter<T>
{
void TakeParameter(T parameter);
}
public static class CustomActivator
{
public static T CreateInstance<T>()
{
return ActivatorUtilities.CreateInstance<T>(_serviceProvider);
}
public static T CreateInstanceWithParam<T, K>(K parameter) where T : IAcceptParameter<K>
{
var instance = ActivatorUtilities.CreateInstance<T>(_serviceProvider);
instance.TakeParameter(parameter);
return instance;
}
}
Changed view model
public class SomeViewModel : IAcceptParameter<Guid>
{
private readonly SomeDependency _someDependency;
private Guid? _userId;
public SomeViewModel(SomeDependency someDependency)
{
_someDependency = someDependency;
}
public void TakeParameter(Guid parameter){
_userId = parameter;
}
}
How I use it
var instanceWithoutParam = CustomActivator.CreateInstance<SomeViewModel>(serviceProvider);
Guid userId;
var instanceWithParam = CustomActivator.CreateInstanceWithParam<SomeViewModel, Guid>(serviceProvider, userId);
Let say you have a class like this:
public class a
{
public string p { get; set; }
public a()
{
p = "default constructor";
}
public a(string pv)
{
p = pv;
}
}
You can use .GetConstructor method to use a specific constructor:
public class Program
{
static void Main(string[] args)
{
var c = typeof(a).GetConstructor(new Type[] { typeof(string) });
if (c != null)
{
var myA = (a)c.Invoke(new object[] { "new value" });
Console.WriteLine($"Value of p is {myA.p}");
}
}
}

C# IServiceScopeFactory - Multiple singleton instances of same type

I have an application which uses a external library to create a client instance for a Db Provider.
This dependency is added as Singleton to my app DI container, and have some parameters which are passed from my app to the initialization constructor of the library.
I need to create another client with different arguments, theoretically can this be achieved?
By my knowledge is that I have to add another singleton class with different arguments to the DI (I am using .NET core IServiceScopeFactory), but how I can resolve the one I need, if both have the same Types.
you can register Provider Factory as singleton
then use it to create your clients
public class DBProviderFactory
{
private static ClientType _clientA { get; set; }
private static ClientType _clientB { get; set; }
private static readonly object ThreadLock = new object();
public ClientType GetInstanceA()
{
if (_clientA != null)
{
return _clientA;
}
lock (ThreadLock)
{
_clientA = new DbInitializer("1", "2");
}
return _clientA;
}
public ClientType GetInstanceB()
{
if (_clientB != null)
{
return _clientA;
}
lock (ThreadLock)
{
_clientB = new DbInitializer("3", "4");
}
return _clientB;
}
}
first register it
services.AddSingleton<DBProviderFactory>();
then use it as below
public class service
{
private ClientType client { get; set; }
public service(DBProviderFactory dBProviderFactory)
{
client = dBProviderFactory.GetInstanceA();
}
}

Unity Dependency Injection Resolve returning System.NullReferenceException

I'm trying to "resolve" a class using Unity Dependency Injection, but Unity always returns me System.NullReferenceException
private IUnityContainer _unityContainer { get; set; }
public void myMethod()
{
_unityContainer = UnityContainer.UnityContainerConfig.Initialize();
IMyclass ObjMyClass = _unityContainer.Resolve<IMyclass >();
ObjMyClass .Init();
}
My container:
public class UnityContainerConfig
{
public static IUnityContainer _unityContainer = null;
public static IUnityContainer Initialize()
{
if (_unityContainer == null)
{
_unityContainer = new Microsoft.Practices.Unity.UnityContainer()
.RegisterType<IRepository<Table1>, Table1Repository>(new HttpContextLifetimeManager<IRepository<Table1>>())
.RegisterType<IRepository<Table2>, Table2Repository>(new HttpContextLifetimeManager<IRepository<Table2>>())
.RegisterType<IRepository<Table3>, Table3Repository>(new HttpContextLifetimeManager<IRepository<Table3>>())
.RegisterType<IRepository<Table4>, Table4Repository>(new HttpContextLifetimeManager<IRepository<Table4>>())
.RegisterType<IMyclass, MyClass>(new HttpContextLifetimeManager<IMyclass>());
}
}
return unityContainer;
}
There are 4 parameters in "my class" constructor which receives the "4 tables as repository"
The problem have been solved.
I had to re-install the unity (nuget), install UnityOfWork and register the "UnityOfWork class"

Unity.AutoRegistration ?? Convention Based Registration Unity

My code is as follows
IUnityContainer container = new UnityContainer();
container
.ConfigureAutoRegistration()
.LoadAssemblyFrom(typeof(Test).Assembly.Location)
.LoadAssemblyFrom(typeof(ITest).Assembly.Location)
.ApplyAutoRegistration();
This is my first question.
I'm not sure whether I have used the LoadAssemblyFrom method correctly here:
ITest test = container.Resolve<ITest>();
When I try to compile I get the exception "ResolutionFailedException".
What am I doing wrong?
Thanks for your time in advance.
It appears that what you are looking for is this:
container.ConfigureAutoRegistration()
.LoadAssemblyFrom(typeof(ITest).Assembly.Location)
.LoadAssemblyFrom(typeof(Test).Assembly.Location)
.Include(If.ImplementsITypeName, Then.Register())
.ApplyAutoRegistration();
This will tell Unity.AutoRegistration to register all types where there is an interface with the same name, prefixed with I.
Here is a complete working console example showing how to set Unity up for registration by convention, then transfer control into the dependency injection world. You will have to add the Unity NuGet package for this to work.
Tested with Unity v3.5 and VS 2012.
#region
using System;
using Microsoft.Practices.Unity;
#endregion
namespace Demo___Unity
{
internal class Program
{
private static void Main(string[] args)
{
using (var container = new UnityContainer())
{
// Manual method.
//container.RegisterType<IEntryPoint, EntryPoint>();
//container.RegisterType<IInjected, Injected>();
// Set up registration by convention.
// http://blogs.msdn.com/b/agile/archive/2013/03/12/unity-configuration-registration-by-convention.aspx
container.RegisterTypes(
AllClasses.FromAssembliesInBasePath(),
WithMappings.FromMatchingInterface,
WithName.Default,
WithLifetime.ContainerControlled);
var controller = container.Resolve<IEntryPoint>();
controller.Main();
}
}
}
public interface IEntryPoint
{
string Name { get; set; }
void Main();
}
public class EntryPoint : IEntryPoint
{
private readonly IInjected Injected;
public EntryPoint(IInjected injected)
{
Injected = injected;
}
public void Main()
{
Console.Write("Hello, world!\n");
Injected.SubMain();
Injected2.SubMain();
Console.Write("[any key to continue]");
Console.ReadKey();
}
// Demonstrates property injection.
[Dependency]
public IInjected Injected2 { get; set; }
public string Name { get; set; }
}
public interface IInjected
{
void SubMain();
}
public class Injected : IInjected
{
public void SubMain()
{
Console.Write("Hello, sub world!\n");
}
public string Name { get; set; }
}
}

Can the WindsorContainer pass a object through the resolve tree when using a factory

I have a problem like this:
public interface IBaseVMFactory
{
public BaseVm Create(TransientDependency otherVM);
}
public class BaseVM
{
BaseVM(ChildVM1 child1, ChildVM2 child2)
}
public class ChildVM1
{
ChildVM1(TransientDependency otherVM)
}
All my viewModels (..VM) needs to be transient. And I need for the childVM1 to get the same instance of otherVM as given to the factory.
I tried to register the BaseVm as ScopedLifestyle, and manually implementing the factory and passing the instance when resolving inside the scope.
But still I get a new instance of the otherVM when resolving.
Am I missing something obvious here?
Kjetil.
I tried reproducing your problem with Windsor 3.2 with the code below:
using System.Diagnostics;
using Castle.Facilities.TypedFactory;
using Castle.MicroKernel.Registration;
using Castle.Windsor;
namespace ConsoleApplication2
{
public class SomeViewModel
{
public SomeViewModel(ISomeFactory factory)
{
var dependency1 = factory.CreateSomeDependency();
var dependency2 = factory.CreateSomeDependency();
Debug.Assert(dependency1 != dependency2);
Debug.Assert(dependency1.Dep == dependency2.Dep);
}
}
public class SomeDependency
{
private readonly DepDep _dep;
public SomeDependency(DepDep dep)
{
_dep = dep;
}
public DepDep Dep
{
get { return _dep; }
}
}
public class DepDep
{
}
public interface ISomeFactory
{
SomeDependency CreateSomeDependency();
}
class Program
{
static void Main(string[] args)
{
var container = new WindsorContainer();
container.AddFacility<TypedFactoryFacility>();
container.Register(
Component.For<SomeViewModel>().LifestyleTransient(),
Component.For<SomeDependency>().LifestyleTransient(),
Component.For<DepDep>().LifestyleBoundTo<SomeViewModel>(),
Component.For<ISomeFactory>().AsFactory().LifestyleTransient()
);
container.Resolve<SomeViewModel>();
}
}
}
To my suprise this just works. So it seems that the factory is now taking over the scope of the context in which it is created. I hope this will help you.
Kind regards,
Marwijn.

Categories