如何使用autofac通过字符串解析具有第三方通用接口的类

时间:2019-07-14 01:33:14

标签: c# dependency-injection interface autofac

在autofac中使用相同的通用接口注册了不同的类,但是使用了不同的类模型。我需要的是在不知道类模型的情况下使用字符串来解析类。我不确定是否可以轻松实现。有任何建议请。

我正在使用控制台应用程序,由于我们收到一个字符串,所以我不知道类模型。我已经在开始课程中注册了所有课程,但是我想在不知道课程模型的情况下解析该课程。我不想使用是否要说,如果string ==“ something”然后解决了,如果解决了此问题。我正在寻找最佳实践。

public TestModel1 { }
public TestModel2 { }

public interface ICalculator<string, T> {}
public Impl1: ICalculator<string, TestModel1> {}
public Impl2: ICalculator<string, TestModel2> {}

在Autofac中,我的注册方式如下:

builder.Register<Impl1>.As<ICalculator<string, TestModel1>>();
builder.Register<Impl2>.As<ICalculator<string, TestModel2>>();

在控制台应用程序中,我想执行以下操作: container。通过字符串解析而不是像这样

if (...) {
class = container.resolve<ICalculator<string, TestModel1>>()
} else {
class = container.resolve<ICalculator<string, TestModel2>>()
}

我希望能够在控制台应用程序中执行以下操作:

var class = container.resolve<ICalculator>("pass string");

1 个答案:

答案 0 :(得分:1)

AFAIK您只能解析您注册的内容。因此,您无法从<script> $(document).ready(function () { $("#fileButton").click(function () { var files = $("#fileInput").get(0).files; var fileData = new FormData(); for (var i = 0; i < files.length; i++) { var newFileName = files[i].filename + "code-" + Math.random().toString(36).substring(7); fileData.append("fileInput", files[i]); } $.ajax({ type: "POST", url: "/AjaxFileUpload/UploadFiles", dataType: "json", contentType: false, processData: false, data: fileData, success: function (result, status, xhr) { var fileObj = "<p>" + JSON.stringify(result).replace(/[\[\]"]+/g, "") + "</p>"; $("#fileUploadStatus").append(fileObj); $("#fileModal").modal("show"); }, error: function (xhr, status, error) { alert(status); } }); }); $(document).ajaxStart(function () { $("#loadingImg").show(); $("#fileButton").prop('disabled', true); }); $(document).ajaxStop(function () { $("#loadingImg").hide(); $("#fileButton").prop('disabled', false); $("#fileInput").val(""); }); }); </script> 获得ICalculator,因为这是两个截然不同的接口。

使用Named Services。您可以执行以下操作:

假设:

ICalculator<string, TestModel2>

注册:

public class Impl1 : ICalculator<string, TestModel1> {}
public class Impl2 : ICalculator<string, TestModel1> {}
// Notice these are the same ---------------------^
// If these need to be different use #2 (Below)

通过以下方式解决了该问题:

builder.Register<Impl1>.Named<ICalculator<string, TestModel1>>("pass string1");
builder.Register<Impl2>.Named<ICalculator<string, TestModel1>>("pass string2");
// Notice these are the same ------------------------------^

或2。

首先创建一个基本接口:

var r = container.resolve<ICalculator<string, TestModel1>>("pass string2) 
// = Impl2

注册:

public interface ICalculator {}
public interface ICalculator<T1, T2> : ICalcuator;

public class Impl1 : ICalculator<string, TestModel1> {}
public class Impl2 : ICalculator<string, TestModel2> {}

通过“

解决
builder.Register<Impl1>.Named<ICalculator>("pass string1");
builder.Register<Impl2>.Named<ICalculator>("pass string2");

如果您的控制台应用程序(或真实应用程序)非常复杂,您应该真正考虑使用范围来帮助控制对象的生命周期:

var r = container.resolve<ICalculator>("pass string2) 
// = Impl2

然后

builder
  .Register<Impl1>
  .Named<ICalculator<string, TestModel1>>("pass string1")
  .InstancePerLifetimeScope();
builder
  .Register<Impl2>
  .Named<ICalculator<string, TestModel1>>("pass string2")
  .InstancePerLifetimeScope();
  

但是,我面临的问题是该接口来自另一个团队开发的库。

在这种情况下,您可以尝试注册泛型,然后让DI解析而不是在实现过程中知道泛型类型:

using (scope1 = container.BeginLifetimeScope())
{
  var r = scope1.Resolve<ICalculator>("pass string1");
  // r would be disposed if it implemented IDisposable
  // before scope1 is `Disposed()`
}

输出:

  

Impl2`2 [System.String,Model1]

DotNetFiddle Example