简体   繁体   English

在dll中动态调用方法时如何使用依赖注入(unity)?

[英]How to use Dependency Injection (unity) when dynamically invoke method in a dll?

I have a project which dynamically invokes methods from dlls. 我有一个项目,可以从dll动态调用方法。 The dll names are defined in a configuration file. dll名称在配置文件中定义。 Below, it is the code to invoke the method 'Run'. 下面是调用方法“运行”的代码。

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));
}

Each DLL is a class which inherts from the same base class MyTask, and override the method Run. 每个DLL是一个类,该类从相同的基类MyTask继承,并覆盖方法Run。 Now, we want to use Dependency Injection with Unity in the each class. 现在,我们要在每个类中对Unity使用依赖注入。 Obviously, we can apply Unity in each DLL. 显然,我们可以在每个DLL中应用Unity。 However, I have a question: 但是,我有一个问题:

Since all DLL are inherted from the same base class MyTask, is it possible to do the dependency injection when it invoke the method 'Run'? 由于所有DLL是从相同的基类MyTask继承的,因此在调用方法“运行”时是否可以进行依赖项注入? I would think we can do it when CreateInstance, pass the parameters for the injection. 我认为我们可以在CreateInstance传递注入参数时做到这一点。 However, different DLLs may need to inject different services. 但是,不同的DLL可能需要注入不同的服务。 So, I got stuck in here. 所以,我被困在这里。

Anyone had this similar situations before? 有人以前有过类似情况吗? Any suggestions? 有什么建议么?

Thanks 谢谢

Since you're loading the type at run-time, you need a factory. 由于要在运行时加载类型,因此需要工厂。 Well, that factory can receive the same injections, and just pass them along. 好吧,那个工厂可以接受相同的注射,然后将它们传递下去。 For example: 例如:

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);
    }
}

Then you register the factory: 然后您注册工厂:

public static UnityContainer CompositionRoot()
{
    var container = new UnityContainer();
    container.RegisterType<IDependency1, Dependency1>();
    container.RegisterType<IDependency2, Dependency2>();
    container.RegisterType<IFactory,Factory>();
    return container;
}

And inject it into the class that will need the external class: 并将其注入需要外部类的类中:

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
    }
}

And the dependencies get passed along just fine. 依赖关系也很好地传递了。

If you find that different libraries need different injections, you can manage all of that in the factory, which is where that sort of logic belongs. 如果发现不同的库需要不同的注入,则可以在工厂中管理所有逻辑,这就是这种逻辑所属的地方。

If the derived type has different constructor parameters and different injections, or the parameters are in an unknown order, you can resolve the dependencies with a bit of LINQ like this: 如果派生类型具有不同的构造函数参数和不同的注入,或者参数的顺序未知,则可以使用一些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;
}

Then just pass it your dependencies in an array and it'll figure out which ones are needed and where to put them: 然后只需将您的依赖项传递到数组中,它将确定需要哪些依赖项以及将它们放在哪里:

return (BaseClass)TryInject(type, args);

See my full working example on DotNetFiddle 请参阅我在DotNetFiddle上的完整工作示例

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

相关问题 如何使用Unity进行依赖项注入(简单示例) - How to use Unity for dependency injection (simple example) 动态调用DLL中的方法 - Dynamically invoke a method in DLL 当没有显式注入依赖项时,如何使用依赖关系注入来覆盖方法或设置默认方法? - How can I use Dependency Injection to either Override a method or to set a default method when no dependency is explicitly injected? 如何在方法或属性中使用依赖项注入? - How to use dependency injection in a method or property? 首先如何从迁移代码中将依赖注入与Unity结合使用? - How use Dependency Injection with Unity from Migration Code First? 使用Unity依赖注入时如何将类型作为参数传递给构造函数 - How to pass a type as parameter to a constructor when using Unity dependency injection 如何动态调用接收回调作为参数的dll方法? - How do i dynamically invoke a dll method that receives a callback as parameter? 如何动态加载托管 dll 并调用返回自定义类的方法? - How to dynamically load a managed dll and invoke a method that returns custom class? 在 static 方法中创建 object 时,如何使用依赖注入? - How can you use dependency injection when creating an object inside of a static method? 依赖注入 - 何时使用属性注入 - Dependency Injection - When to use property injection
 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM