如何解决.net内核中动态控制器的依赖关系



我正在为要从dll加载的类型动态创建控制器。为此,我创建了一个基本控制器来处理动态控制器请求。

我的动态控制器在constructor 中有以下依赖项

public class Order
{
private readonly IDBLogger _logger;
private readonly IExceptionHandler _handler
public Order(IDBLogger logger, IExceptionHandler handler)
{
_logger=logger;
_handler=handler
}
public void GetOrderDetail()
{
_logger.log(".....");   //Here I am getting null reference as I am not able resolve this _logger type.

/// rest code
}
}

既然类是从dll加载的,我该如何解决这个问题。

我认为我对你的目标的假设太离谱了,事实上,在我看来,你根本不需要惹ApplicationParts或FeatureProviders。对我来说,这似乎是DI注册问题。

  1. 我从样板文件.net内核3.1 MVC应用程序开始(没有什么特别之处(
  2. 然后我又添加了两个类库项目:CommonOrders

Common.dll

我假设您的接口(为了简洁起见,我只使用IDBLogger(必须对控制器组件和主应用程序可用。因此,这两个项目都将依赖它

namespace Common
{
public interface IDBLogger
{
void Log(string s);
}
}

订单.dll

该程序集定义了一个webapi控制器:

using Common;
namespace Orders
{
public class Order
{
private readonly IDBLogger _logger;
public Order(IDBLogger logger)
{
_logger = logger;
}
public void GetOrderDetail()
{
_logger.Log("Inside GetOrderDetail");
}
}
}

MVC

由于大多数代码都是标准的,所以我只列出我更改过的文件。注意,现在我依赖于默认的控制器解析器,我只需要在ServiceCollection上注册我的类型

启动.cs

...
public void ConfigureServices(IServiceCollection services)
{
services.AddControllersWithViews(); // add all controllers as you normally would. I think you don't need to mess with ApplicationParts. but if you do, you are already aware that https://stackoverflow.com/questions/36680933/discovering-generic-controllers-in-asp-net-core is a good example
services.AddScoped<IDBLogger, IdbLogger>();
// load assembly and register with DI
var assembly = Assembly.LoadFrom(Path.Combine("..\path\to", "Orders.dll")); 
var orderType = assembly.ExportedTypes.First(t => t.Name == "Order");
services.AddScoped(orderType); // this is where we would make our type known to the DI container
var loadedTypesCache = new LoadedTypesCache(); // this step is optional - I chose to leverage the same DI mechanism to avoid having to load assembly in my controller for type definition. you can probably find a better approach at doing this
loadedTypesCache.LoadedTypes.Add("order", orderType);
services.AddSingleton(loadedTypesCache); // singleton seems like a good fit here
}

IdbLogger.cs

using Common;
using System;
namespace Test
{
public class IdbLogger : IDBLogger
{
public void Log(string s)
{
Console.WriteLine(s); // nothing fancy here either
}
}
}

值控制器.cs

[Route("api/[controller]")]
[ApiController]
public class ValuesController
{
public ValuesController(IServiceProvider serviceProvider, LoadedTypesCache cache)
{
var order = serviceProvider.GetService(cache.LoadedTypes["order"]); // you could load the same assembly here to get the type again, but i opted to inject a dictionary with preloaded type instead

// following two lines are just to call the method. you probably have better way of doing it
var m = cache.LoadedTypes["order"].GetMethod("GetOrderDetail", BindingFlags.Public|BindingFlags.Instance);
m.Invoke(order, new object[] { });
}
[HttpGet]
public IEnumerable<string> Get()
{
return new [] { "value1", "value2" };
}
}

依靠内置的DI容器,我们就不用考虑手动实例化动态加载的类型(以及它们的依赖关系,只要DI容器知道它们(。您可能会发现,必须使用反射来处理这些实例有点麻烦,所以您可能想在那里探索您的选择。

希望这是丢失的

您可以使用反射动态加载依赖项和控制器。有关更多信息,您可以访问以下链接。组件

最新更新