3 回答

TA貢獻1785條經驗 獲得超4個贊
好的,您已經邁出了很好的第一步,認識到Web.config只是另一個依賴項,并將其包裝到ConfigProvider中進行注入是一個很好的解決方案。
但是,您開始陷入MVC的設計問題之一-即,為了實現DI友好性,屬性應僅提供元數據,而從不實際定義行為。這不是測試方法的問題,而是濾波器設計方法的問題。
正如文章中指出的那樣,您可以通過將操作過濾器屬性分為兩部分來解決此問題。
該屬性不包含任何用于標記控制器和操作方法的行為。
一個DI友好類,該類實現IActionFilter并包含所需的行為。
該方法是使用IActionFilter來測試屬性的存在,然后執行所需的行為??梢詾閯幼鬟^濾器提供所有依賴項,然后在組成應用程序時將其注入。
IConfigProvider provider = new WebConfigProvider();
IActionFilter filter = new MaxLengthActionFilter(provider);
GlobalFilters.Filters.Add(filter);
注意:如果您需要過濾器的任何依賴項以使生命周期短于單例,則需要GlobalFilterProvider在此答案中使用as 。
MaxLengthActionFilter的實現如下所示:
public class MaxLengthActionFilter : IActionFilter
{
public readonly IConfigProvider configProvider;
public MaxLengthActionFilter(IConfigProvider configProvider)
{
if (configProvider == null)
throw new ArgumentNullException("configProvider");
this.configProvider = configProvider;
}
public void OnActionExecuted(ActionExecutedContext filterContext)
{
var attribute = this.GetMaxLengthAttribute(filterContext.ActionDescriptor);
if (attribute != null)
{
var maxLength = attribute.MaxLength;
// Execute your behavior here, and use the configProvider as needed
}
}
public void OnActionExecuting(ActionExecutingContext filterContext)
{
var attribute = this.GetMaxLengthAttribute(filterContext.ActionDescriptor);
if (attribute != null)
{
var maxLength = attribute.MaxLength;
// Execute your behavior here, and use the configProvider as needed
}
}
public MaxLengthAttribute GetMaxLengthAttribute(ActionDescriptor actionDescriptor)
{
MaxLengthAttribute result = null;
// Check if the attribute exists on the controller
result = (MaxLengthAttribute)actionDescriptor
.ControllerDescriptor
.GetCustomAttributes(typeof(MaxLengthAttribute), false)
.SingleOrDefault();
if (result != null)
{
return result;
}
// NOTE: You might need some additional logic to determine
// which attribute applies (or both apply)
// Check if the attribute exists on the action method
result = (MaxLengthAttribute)actionDescriptor
.GetCustomAttributes(typeof(MaxLengthAttribute), false)
.SingleOrDefault();
return result;
}
}
并且,不應包含任何行為的屬性應如下所示:
// This attribute should contain no behavior. No behavior, nothing needs to be injected.
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Class, AllowMultiple = false)]
public class MaxLengthAttribute : Attribute
{
public MaxLengthAttribute(int maxLength)
{
this.MaxLength = maxLength;
}
public int MaxLength { get; private set; }
}
使用更寬松的耦合設計,測試屬性的存在要簡單得多。
[TestMethod]
public void Base_controller_must_have_MaxLengthFilter_attribute()
{
var att = typeof(BaseController).GetCustomAttribute<MaxLengthAttribute>();
Assert.IsNotNull(att);
}

TA貢獻1803條經驗 獲得超6個贊
最近,我在這里關于配置“問題”的問題越來越多。它們都有一個共同的基礎-您有幾個需要使用相同配置的項目,服務器和服務。我的建議是-停止使用Web.config。
將所有配置放入數據庫!添加一個包含所有配置鍵和值的表(或幾個表),并在應用程序啟動時讀取它們(global.asax)。
這樣,您不必擔心將配置配置到每個項目中或將其注入到不同的構造函數中。

TA貢獻1883條經驗 獲得超3個贊
實際上,如果您正確地設計了過濾器,那不是不可以的(有理由將它們稱為過濾器)。篩選器的目的僅是確定何時執行共享行為,而不應實際執行共享行為。應該將其委派給一個處理程序,該處理程序的派生方式與ActionResult Microsoft在AuthorizeAttribute中所做的一樣(filterContext.Result僅當需要運行時才進行設置)。
- 3 回答
- 0 關注
- 616 瀏覽
添加回答
舉報