[英]How to use Dependency Injection (unity) when dynamically invoke method in a dll?
我有一个项目,可以从dll动态调用方法。 dll名称在配置文件中定义。 下面是调用方法“运行”的代码。
Assembly a = Assembly.LoadFile(fullpath);
Type t = a.GetType(dll_fullname);
// Run in subclass
MethodInfo mi = t.GetMethod("Run");
if (mi != null)
{
// set log file name
object result = null;
object classInstance = Activator.CreateInstance(t, null);
object[] parametersArray = new object[] { t.Name };
result = mi.Invoke(classInstance, parametersArray);
}
else
{
myEventLog.WriteEntry("Error: Invoke DLL Failed.", EventLogEntryType.Error, (int)(SharedClass.EventId.Error));
}
每个DLL是一个类,该类从相同的基类MyTask继承,并覆盖方法Run。 现在,我们要在每个类中对Unity使用依赖注入。 显然,我们可以在每个DLL中应用Unity。 但是,我有一个问题:
由于所有DLL是从相同的基类MyTask继承的,因此在调用方法“运行”时是否可以进行依赖项注入? 我认为我们可以在CreateInstance传递注入参数时做到这一点。 但是,不同的DLL可能需要注入不同的服务。 所以,我被困在这里。
有人以前有过类似情况吗? 有什么建议么?
谢谢
由于要在运行时加载类型,因此需要工厂。 好吧,那个工厂可以接受相同的注射,然后将它们传递下去。 例如:
public class Factory : IFactory
{
protected readonly IDependency1 _dependency1; //Injected
protected readonly IDependency2 _dependency2; //Injected
public Factory(IDependency1 dependency1, IDependency2 dependency2)
{
_dependency1 = dependency1;
_dependency2 = dependency2;
}
public BaseClass Resolve(string libraryName, string typeName)
{
var assembly = Assembly.LoadFile(libraryName);
var type = assembly.GetType(typeName);
var args = new object [] { _dependency1, _dependency2 };
return (BaseClass)Activator.CreateInstance(type, args);
}
}
然后您注册工厂:
public static UnityContainer CompositionRoot()
{
var container = new UnityContainer();
container.RegisterType<IDependency1, Dependency1>();
container.RegisterType<IDependency2, Dependency2>();
container.RegisterType<IFactory,Factory>();
return container;
}
并将其注入需要外部类的类中:
public class Application
{
protected readonly IFactory _factory;
public Application(IFactory factory)
{
_factory = factory;
}
public void Run()
{
var instance = _factory.Resolve("MyLibrary.dll", "External.DerivedClass");
//Do something with instance
}
}
依赖关系也很好地传递了。
如果发现不同的库需要不同的注入,则可以在工厂中管理所有逻辑,这就是这种逻辑所属的地方。
如果派生类型具有不同的构造函数参数和不同的注入,或者参数的顺序未知,则可以使用一些LINQ来解决依赖性,如下所示:
protected object TryInject(Type concreteType, IEnumerable<object> dependencies)
{
var constructors = concreteType
.GetConstructors
(
BindingFlags.Public | BindingFlags.Instance
)
.OrderByDescending
(
c => c.GetParameters().Length
);
foreach (var c in constructors)
{
var parameters = c.GetParameters();
var arguments = parameters
.Select
(
p => dependencies.FirstOrDefault
(
d => p.ParameterType.IsAssignableFrom(d.GetType())
)
)
.ToArray();
if (!arguments.Contains( null ))
{
return Activator.CreateInstance(concreteType, arguments);
}
}
return null;
}
然后只需将您的依赖项传递到数组中,它将确定需要哪些依赖项以及将它们放在哪里:
return (BaseClass)TryInject(type, args);
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.