我正在检查FilterAttribute
中的.Net Core
类,我发现它有多个在特定时间调用的方法。 E.g:
OnAuthorization(AuthorizationContext) 在进程请求授权时调用。
https://msdn.microsoft.com/en-us/library/system.web.mvc.authorizeattribute(v=vs.118).aspx
我想知道,如果我正在编写自定义属性,我该如何使用其中定义的方法?
答案 0 :(得分:3)
简单地称呼它。
我们制作了一个测试属性:
class TestAttribute : Attribute
{
public void Greet(string text)
{
Console.WriteLine(text);
}
}
使用GetCustomAttribute
我们正在检索该属性,并在其上调用Greet
:
[Test]
class Program
{
static void Main(string[] args)
{
var attribute = typeof(Program).GetCustomAttribute<TestAttribute>();
attribute.Greet("Hello World");
Console.ReadKey();
}
}
相关:
答案 1 :(得分:1)
您分享的链接不是.net core
。在.net core
中,ActionFilterAttribute
类具有制作自定义过滤器所需的所有功能。要创建自定义过滤器,只需创建一个扩展ActionFilterAttribute
的类并覆盖您选择的功能。您可以在此处查看调用过滤器的时间轴:https://docs.microsoft.com/en-us/aspnet/core/mvc/controllers/filters
要使用此过滤器,假设您创建的类名为MyCustomFilterAttribute
,您将在控制器中使用它:
public class LoginController : Controller
{
[MyCustomFilter]
public void Index(){
}
}
如果要为控制器中的每个操作实现过滤器,可以将属性添加到控制器:
[MyCustomFilter]
public class LoginController : Controller
答案 2 :(得分:1)
属性不会自行执行任何操作。像FilterAttribute
这样的属性做任何事情的唯一原因是因为MVC框架在调用它们应用的方法之前或之后查找它们并调用它们。
以下是MVC reference code base中的内容:
protected virtual ActionExecutedContext InvokeActionMethodWithFilters(ControllerContext controllerContext, IList<IActionFilter> filters, ActionDescriptor actionDescriptor, IDictionary<string, object> parameters)
{
ActionExecutingContext preContext = new ActionExecutingContext(controllerContext, actionDescriptor, parameters);
Func<ActionExecutedContext> continuation = () =>
new ActionExecutedContext(controllerContext, actionDescriptor, false /* canceled */, null /* exception */)
{
Result = InvokeActionMethod(controllerContext, actionDescriptor, parameters)
};
// need to reverse the filter list because the continuations are built up backward
Func<ActionExecutedContext> thunk = filters.Reverse().Aggregate(continuation, (next, filter) => () => InvokeActionMethodFilter(filter, preContext, next));
return thunk();
}
在没有上下文的情况下很难遵循,并且很难发现循环(他们使用一些LINQ和Aggregate方法来调用集合中的每个过滤器)但是足以说明MVC会看起来在该方法中,查找某种类型的属性,并在实际的操作方法调用之前和之后调用它们。所以它不是自动的。
如果你愿意编写代码来调用属性,你可以做类似的事情。这是一个如何做的例子。
首先,我们定义自定义属性。此自定义属性将在调用其OnBeforeExecute
方法时向控制台输出消息。
public class HelloWorldAttribute : System.Attribute
{
private string _someString;
public HelloWorldAttribute(string text)
{
_someString = text;
}
public void OnBeforeExecute()
{
Console.WriteLine("OnBeforeExecute says '{0}'.", _someString);
}
}
现在我们编写一个将该属性应用于其中一个方法的类:
public class MyClass
{
[HelloWorld("This is a test!!")]
public void MyClassMethod(string text)
{
Console.WriteLine("MyClassMethod says '{0}'", text);
}
}
现在,该属性在运行时不执行任何操作:
public class Program
{
public static void Main()
{
//By itself, the attribute does nothing
var c = new MyClass();
c.MyClassMethod("Main call");
}
}
输出:
MyClassMethod says 'Main call'
但是如果我们编写代码来查找属性并调用它,我们就可以显示消息了。这是一个非常简单的例子:
public class Program
{
public static void Main()
{
var c = new MyClass();
typeof(MyClass)
.GetMethod(nameof(c.MyClassMethod))
.GetCustomAttributes(true)
.OfType<HelloWorldAttribute>()
.First()
.OnBeforeExecute();
c.MyClassMethod("Main call");
}
}
输出:
OnBeforeExecute says 'This is a test!!'.
MyClassMethod says 'Main call'
答案 3 :(得分:1)
不是100%肯定你在问什么,但是这里有一些超人为的演示代码可以访问方法和归因方法
class Program
{
public class Hook : Attribute
{
public string Action { get; set; }
public void Talk(string s)
{
var prefix = string.IsNullOrEmpty(Action) ? "" : $"{Action} ";
Console.WriteLine($"{prefix}{s}");
}
}
public class A
{
[Hook] public string Option1()=> "A1";
public string Option2() => "A2";
}
public class B
{
[Hook(Action = "Blah")] public string Option1() => "B1";
[Hook] public string Option2() => "B2";
}
static void Main(string[] args)
{
var things = new List<object>() {new A(), new B()};
things.SelectMany(t => t.GetType().GetMethods()
.Select(m => (method: m, attribute: m.GetCustomAttribute(typeof(Hook), true) as Hook))
.Where(h => h.attribute != null)
.Select(h => (target: t, hook: h)))
.ToList()
.ForEach(v => v.hook.attribute.Talk(v.hook.method.Invoke(v.target, new object[] { }).ToString()));
}
}