似乎没有一种简单的方法可以确保控制器具有属性注入。
解决这个问题的方法是单独注册所有控制器,这似乎有点失败了。 Sub TU_Levenshtein()
Call Levenshtein("democrat", "republican")
Call Levenshtein("ooo", "u")
Call Levenshtein("ceci est un test", "ceci n'est pas un test")
End Sub
Sub Levenshtein(ByVal string1 As String, ByVal string2 As String)
' Fill Matrix Levenshtein (-> array 'Distance')
Dim i As Long, j As Long
Dim string1_length As Long
Dim string2_length As Long
Dim distance() As Long
string1_length = Len(string1)
string2_length = Len(string2)
ReDim distance(string1_length, string2_length)
For i = 0 To string1_length
distance(i, 0) = i
Next
For j = 0 To string2_length
distance(0, j) = j
Next
For i = 1 To string1_length
For j = 1 To string2_length
If Asc(Mid$(string1, i, 1)) = Asc(Mid$(string2, j, 1)) Then
distance(i, j) = distance(i - 1, j - 1)
Else
distance(i, j) = Application.WorksheetFunction.min _
(distance(i - 1, j) + 1, _
distance(i, j - 1) + 1, _
distance(i - 1, j - 1) + 1)
End If
Next
Next
LevenshteinDistance = distance(string1_length, string2_length) ' for information only
' Write Matrix on VBA sheets (only for visuation, not used in calculus)
Cells.Clear
For i = 1 To UBound(distance, 1)
Cells(i + 2, 1).Value = Mid(string1, i, 1)
Next i
For i = 1 To UBound(distance, 2)
Cells(1, i + 2).Value = Mid(string2, i, 1)
Next i
For i = 0 To UBound(distance, 1)
For j = 0 To UBound(distance, 2)
Cells(i + 2, j + 2) = distance(i, j)
Next j
Next i
' One solution
current_posx = UBound(distance, 1)
current_posy = UBound(distance, 2)
Do
cc = distance(current_posx, current_posy)
Cells(current_posx + 1, current_posy + 1).Interior.Color = vbYellow ' visualisation again
' Manage border case
If current_posy - 1 < 0 Then
MsgBox ("deletion. " & Mid(string1, current_posx, 1))
current_posx = current_posx - 1
current_posy = current_posy
GoTo suivant
End If
If current_posx - 1 < 0 Then
MsgBox ("insertion. " & Mid(string2, current_posy, 1))
current_posx = current_posx
current_posy = current_posy - 1
GoTo suivant
End If
' Middle cases
cc_L = distance(current_posx, current_posy - 1)
cc_U = distance(current_posx - 1, current_posy)
cc_D = distance(current_posx - 1, current_posy - 1)
If (cc_D <= cc_L And cc_D <= cc_U) And (cc_D = cc - 1 Or cc_D = cc) Then
If (cc_D = cc - 1) Then
MsgBox "substitution. " & Mid(string1, current_posx, 1) & " by " & Mid(string2, current_posy, 1)
current_posx = current_posx - 1
current_posy = current_posy - 1
GoTo suivant
Else
MsgBox "no operation"
current_posx = current_posx - 1
current_posy = current_posy - 1
GoTo suivant
End If
ElseIf cc_L <= cc_D And cc_L = cc - 1 Then
MsgBox ("insertion. " & Mid(string2, current_posy, 1))
current_posx = current_posx
current_posy = current_posy - 1
GoTo suivant
Else
MsgBox ("deletion." & Mid(string1, current_posy, 1))
current_posx = current_posx
current_posy = current_posy - 1
GoTo suivant
End If
suivant:
Loop While Not (current_posx = 0 And current_posy = 0)
End Sub
属性为removed,他们特别提到应该由各个IoC容器决定这一点。
我错过了一些明显的东西吗?查找所有可用的扩展方法,但没有找到任何内容,相同的问题和讨论论坛。
答案 0 :(得分:1)
是的,使用autofac为控制器设置属性注入有点棘手;),但这是它的工作原理。
使用ASP.NET Core(2.1),首先需要在Startup.cs
中将控制器注册为服务:
services.AddMvc().AddControllersAsServices();
否则,属性注入将无法如autofac docs中所述:
默认情况下,ASP.NET Core会从容器中解析控制器参数,但实际上不会从容器中解析控制器。这通常不是问题,但是它的意思是:[...] 您在控制器注册过程中可能进行的特殊接线(例如设置属性注入)将不起作用。 >
然后,您需要通过populate
向autofac容器构建器注册服务,然后,您可以向autofac容器注册控制器。
这是autofac docs的简短代码摘录:
public IServiceProvider ConfigureServices(IServiceCollection services)
{
services.AddMvc().AddControllersAsServices();
var builder = new ContainerBuilder();
builder.Populate(services);
builder.RegisterType<MyController>().PropertiesAutowired();
this.ApplicationContainer = builder.Build();
return new AutofacServiceProvider(this.ApplicationContainer);
}
请务必附加.PropertiesAutowired()
以便进行属性注入!
现在另一件事可能并不明显,那就是autofac的PropertiesAutowired
不会自动将服务的每个属性视为属性注入的麻烦。
从github source code中检出DefaultPropertySelector
,您会看到它会跳过非公开的内容:
if (!propertyInfo.CanWrite || propertyInfo.SetMethod?.IsPublic != true)
{
return false;
}
因此,您可能需要创建自定义PropertySelector
来扩展DefaultPropertySelector
,以便根据自己的逻辑将属性注册为可注入的。因此,您可以执行以下操作:
var propSelector = new MyPropertySelector();
builder.RegisterType<MyController>().PropertiesAutowired(propSelector);
为了确保您不必总是记住每个控制器类,还可以批量注册所有控制器:
builder.Populate(services);
var propSelector = new MyPropertySelector();
builder
.RegisterAssemblyTypes(typeof(Controller).Assembly)
.AssignableTo<Controller>()
.InstancePerLifetimeScope()
.PropertiesAutowired(propSelector);
希望这会有所帮助:)
答案 1 :(得分:1)
我试过了
builder.Populate(services);
var propSelector = new MyPropertySelector();
builder
.RegisterAssemblyTypes(typeof(Controller).Assembly)
.AssignableTo<Controller>()
.InstancePerLifetimeScope()
.PropertiesAutowired(propSelector);
但它对我不起作用,所以我使用了从官方网站获取的以下代码片段。
var dataAccess = Assembly.GetExecutingAssembly();
builder.RegisterAssemblyTypes(dataAccess)
.Where(t => t.Name.EndsWith("Controller"))
.InstancePerLifetimeScope()
.PropertiesAutowired();
https://autofaccn.readthedocs.io/en/latest/register/scanning.html