Dependency Injection on Activator Createinstance Reflection
Hi all.
I am trying to reflect all classes of a specific interface and run a method. This works until i try to use services into the class constructor, like the IScopeProvider.
So i need to be able to get my Activator.CreateInstance(type) to pick up all paramaters in the constructor with Dependency Injection.
Does anyone know what to do?
This is what i have:
My interface to find
public interface IFindMe
{
string Name { get; }
void PerformRun();
}
Class to reflect
public class TestJob : IFindMe
{
private readonly IScopeProvider _scopeProvider;
public TestJob(IScopeProvider scopeProvider)
{
_scopeProvider = scopeProvider;
}
public string Name => "Find me ffs";
public void PerformRunAsync()
{
using (var scope = _scopeProvider.CreateScope(autoComplete: true))
{
// Just to try something
var instanceId = scope.InstanceId;
}
}
}
IComponent, where all the interfaces are picked up
public class FindMeComponent : IComponent
{
private readonly ILogger _logger;
public FindMeComponent(ILogger logger)
{
// When it works i wanna log things :)
_logger = logger;
}
public void Initialize()
{
var listOfTypes = new List<Type>();
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
foreach (var assembly in assemblies)
{
try
{
var foundTypes = assembly.GetTypes();
listOfTypes.AddRange(foundTypes);
}
catch (ReflectionTypeLoadException e)
{
var exceptionTypes = e.Types.Where(t => t != null);
listOfTypes.AddRange(exceptionTypes);
}
}
var type = typeof(IFindMe);
var types = listOfTypes.Where(t => type.IsAssignableFrom(t) && !t.IsInterface);
foreach (var type in types)
{
// This works until i use a class that has parameters in the contructor.
object calcInstance = Activator.CreateInstance(type);
var name = (string)type.GetProperty("Name").GetValue(calcInstance, null);
var methodInfo = _type.GetMethod("PerformRun");
methodInfo.Invoke(_calcInstance, null);
}
}
public void Terminate()
{
}
}
IUserComposer, where i register the FindMeComponent
public class Installer : IUserComposer
{
public void Compose(Composition composition)
{
composition.Components().Append<FindMeComponent>();
}
}
I got it to work. I dunno if its the best solution, but its the only one i can come around.
So basically you have to make sure there is only one constructor. And that constructor either have to be parameterless or only contain of Dependency Injection services. And from what i could search me to, its called Bastard Injection DI anti-pattern.
Then you need to find out if the constructor have parameters or not. If the constructor have parameters, you find each parameter and get the instance of its type Umbraco.Web.Composing.Current.Factory.GetInstance and then you pass the instances as an object array into the Activator.CreateInstance
public void Initialize()
{
var listOfTypes = new List<Type>();
var assemblies = AppDomain.CurrentDomain.GetAssemblies();
foreach (var assembly in assemblies)
{
try
{
var foundTypes = assembly.GetTypes();
listOfTypes.AddRange(foundTypes);
}
catch (ReflectionTypeLoadException e)
{
var exceptionTypes = e.Types.Where(t => t != null);
listOfTypes.AddRange(exceptionTypes);
}
}
var typeOfInterface = typeof(IFindMe);
var types = listOfTypes.Where(t => typeOfInterface.IsAssignableFrom(t) && !t.IsInterface);
foreach (var type in types)
{
object calcInstance = null;
var constructors = type.GetConstructors();
var firstConstrutor = constructors.FirstOrDefault(); // Bastard Injection DI anti-pattern
if (firstConstrutor != null)
{
var constructorParameters = firstConstrutor.GetParameters();
if (constructorParameters != null && constructorParameters.Any())
{
var objectList = new List<object>();
foreach (var constructorParameter in constructorParameters)
{
var cpType = constructorParameter.ParameterType;
var instance = Umbraco.Web.Composing.Current.Factory.GetInstance(cpType);
objectList.Add(instance);
}
calcInstance = Activator.CreateInstance(type, objectList.ToArray());
}
}
if (calcInstance == null)
{
calcInstance = Activator.CreateInstance(type);
}
var name = (string)type.GetProperty("Name").GetValue(calcInstance, null);
var methodInfo = type.GetMethod("PerformRun");
methodInfo.Invoke(calcInstance, null);
}
}
Dependency Injection on Activator Createinstance Reflection
Hi all.
I am trying to reflect all classes of a specific interface and run a method. This works until i try to use services into the class constructor, like the IScopeProvider.
So i need to be able to get my
Activator.CreateInstance(type)
to pick up all paramaters in the constructor with Dependency Injection.Does anyone know what to do?
This is what i have:
My interface to find
Class to reflect
IComponent, where all the interfaces are picked up
IUserComposer, where i register the FindMeComponent
I dunno why it is always putting it under
Using Umbraco And Getting Started
I got it to work. I dunno if its the best solution, but its the only one i can come around.
So basically you have to make sure there is only one constructor. And that constructor either have to be parameterless or only contain of Dependency Injection services. And from what i could search me to, its called Bastard Injection DI anti-pattern.
Then you need to find out if the constructor have parameters or not. If the constructor have parameters, you find each parameter and get the instance of its type
Umbraco.Web.Composing.Current.Factory.GetInstance
and then you pass the instances as an object array into theActivator.CreateInstance
is working on a reply...
This forum is in read-only mode while we transition to the new forum.
You can continue this topic on the new forum by tapping the "Continue discussion" link below.