如何在 Azure 移动应用服务客户端中实施 AOP?
How do I implement AOP in an Azure Mobile App Services client?
在使用 MVC 5、Web API 2.0 和 EF Core 1.0 的 Azure 移动应用服务服务器端应用程序上,可以像这样装饰控制器以实现基于令牌的身份验证:
// Server-side EF Core 1.0 / Web API 2 REST API
[Authorize]
public class TodoItemController : TableController<TodoItem>
{
protected override void Initialize(HttpControllerContext controllerContext)
{
base.Initialize(controllerContext);
DomainManager = new EntityDomainManager<TodoItem>(context, Request);
}
// GET tables/TodoItem
public IQueryable<TodoItem> GetAllTodoItems()
{
return Query();
}
...
}
我希望能够在客户端做一些类似的事情,我在上面用 [Authorize] 之类的东西装饰一个方法,也许在下面用 [Secured] 装饰:
public class TodoItem
{
string id;
string name;
bool done;
[JsonProperty(PropertyName = "id")]
public string Id
{
get { return id; }
set { id = value;}
}
[JsonProperty(PropertyName = "text")]
public string Name
{
get { return name; }
set { name = value;}
}
[JsonProperty(PropertyName = "complete")]
public bool Done
{
get { return done; }
set { done = value;}
}
[Version]
public string Version { get; set; }
}
// Client side code calling GetAllTodoItems from above
[Secured]
public async Task<ObservableCollection<TodoItem>> GetTodoItemsAsync()
{
try
{
IEnumerable<TodoItem> items = await todoTable
.Where(todoItem => !todoItem.Done)
.ToEnumerableAsync();
return new ObservableCollection<TodoItem>(items);
}
catch (MobileServiceInvalidOperationException msioe)
{
Debug.WriteLine(@"Invalid sync operation: {0}", msioe.
}
catch (Exception e)
{
Debug.WriteLine(@"Sync error: {0}", e.Message);
}
return null;
}
其中 [Secured] 可能定义如下:
public class SecuredFilterAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
// Check if user is logged in, if not, redirect to the login page.
}
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
// Check some globally accessible member to see if user is logged out.
}
}
不幸的是,根据 "Creating Custom Action Filters" 上的 Microsoft 文章,上述代码仅适用于 MVC 1.0 应用程序及更高版本的控制器:https://msdn.microsoft.com/en-us/library/dd381609(v=vs.100).aspx
如何实现类似于 "Custom Action Filter" 的功能,使我能够在移动应用服务客户端而不是服务器中使用“[Secured]”装饰?答案将帮助我从客户端创建自定义身份验证并将代码保存在一个位置而不会使实现复杂化,即它是一个横切关注点,如性能指标、重复尝试的自定义执行计划、日志记录等。
使场景复杂化的是,客户端还为 iOS 实现了 Xamarin.Forms,并且由于 iOS 对本机代码的要求,它必须是功能性的提前模式,JIT 是还不可能。
一些不同的人知道您更笼统地描述的内容 names/terms。首先想到的是"Aspect Oriented Programming"(简称AOP)。它处理所谓的 cross cutting concerns。我敢打赌你想做两件事中的一件
- 以标准化有意义的方式记录 exceptions/messages
- 记录 times/performance 系统区域
从一般意义上讲,是的,C# 能够做这样的事情。网上会有无数的教程教你如何做,这样回答太笼统了。
然而,asp.netMVC 的作者对这些事情深思熟虑,并为您提供了许多如您所描述的属性,可以根据需要进行扩展,并提供对管道的轻松访问向开发人员提供他们需要的所有信息(例如当前路由、任何参数、任何异常、任何 authorization/authentication 请求等)
这将是一个很好的起点:http://www.strathweb.com/2015/06/action-filters-service-filters-type-filters-asp-net-5-mvc-6/
这看起来也不错:http://www.dotnetcurry.com/aspnet-mvc/976/aspnet-mvc-custom-action-filter
属性在您描述的场景中起作用的原因是因为其他代码负责实际调用方法或读取属性,而其他代码将查找属性并相应地修改行为。当您只是 运行 C# 代码时,您通常不会得到它;没有一种本地方法可以在执行方法之前执行属性中的代码。
从您的描述来看,您似乎在追求面向方面的编程。有关框架列表,请参阅 What is the best implementation for AOP in .Net?。
本质上,使用适当的 AOP 框架,您可以添加属性或其他标记,并在编译时执行或插入代码。有很多方法,因此我不是很具体,抱歉。
您确实需要了解 AOP 方法不同于 ASP.Net MVC 之类的方法,因为 AOP 通常会修改您的运行时代码(无论如何在我的理解中,我确信它也有变化)。
至于 AOP 是否真的可行将取决于您的要求,但我会谨慎行事 - 这不适合胆小的人。
此问题的一个完全替代解决方案是查看类似 Mediatr 或类似的东西,将您的逻辑分解为一组命令,您可以通过消息总线调用这些命令。有用的原因是您可以使用各种类型的逻辑(包括授权逻辑)装饰您的消息总线(或管道)。该解决方案与您要求的非常不同 - 但无论如何可能更可取。
或者只是将单行授权调用添加为每个方法中的第一行,而不是将其作为属性...
在使用 MVC 5、Web API 2.0 和 EF Core 1.0 的 Azure 移动应用服务服务器端应用程序上,可以像这样装饰控制器以实现基于令牌的身份验证:
// Server-side EF Core 1.0 / Web API 2 REST API
[Authorize]
public class TodoItemController : TableController<TodoItem>
{
protected override void Initialize(HttpControllerContext controllerContext)
{
base.Initialize(controllerContext);
DomainManager = new EntityDomainManager<TodoItem>(context, Request);
}
// GET tables/TodoItem
public IQueryable<TodoItem> GetAllTodoItems()
{
return Query();
}
...
}
我希望能够在客户端做一些类似的事情,我在上面用 [Authorize] 之类的东西装饰一个方法,也许在下面用 [Secured] 装饰:
public class TodoItem
{
string id;
string name;
bool done;
[JsonProperty(PropertyName = "id")]
public string Id
{
get { return id; }
set { id = value;}
}
[JsonProperty(PropertyName = "text")]
public string Name
{
get { return name; }
set { name = value;}
}
[JsonProperty(PropertyName = "complete")]
public bool Done
{
get { return done; }
set { done = value;}
}
[Version]
public string Version { get; set; }
}
// Client side code calling GetAllTodoItems from above
[Secured]
public async Task<ObservableCollection<TodoItem>> GetTodoItemsAsync()
{
try
{
IEnumerable<TodoItem> items = await todoTable
.Where(todoItem => !todoItem.Done)
.ToEnumerableAsync();
return new ObservableCollection<TodoItem>(items);
}
catch (MobileServiceInvalidOperationException msioe)
{
Debug.WriteLine(@"Invalid sync operation: {0}", msioe.
}
catch (Exception e)
{
Debug.WriteLine(@"Sync error: {0}", e.Message);
}
return null;
}
其中 [Secured] 可能定义如下:
public class SecuredFilterAttribute : ActionFilterAttribute
{
public override void OnActionExecuting(ActionExecutingContext filterContext)
{
// Check if user is logged in, if not, redirect to the login page.
}
public override void OnActionExecuted(ActionExecutedContext filterContext)
{
// Check some globally accessible member to see if user is logged out.
}
}
不幸的是,根据 "Creating Custom Action Filters" 上的 Microsoft 文章,上述代码仅适用于 MVC 1.0 应用程序及更高版本的控制器:https://msdn.microsoft.com/en-us/library/dd381609(v=vs.100).aspx
如何实现类似于 "Custom Action Filter" 的功能,使我能够在移动应用服务客户端而不是服务器中使用“[Secured]”装饰?答案将帮助我从客户端创建自定义身份验证并将代码保存在一个位置而不会使实现复杂化,即它是一个横切关注点,如性能指标、重复尝试的自定义执行计划、日志记录等。
使场景复杂化的是,客户端还为 iOS 实现了 Xamarin.Forms,并且由于 iOS 对本机代码的要求,它必须是功能性的提前模式,JIT 是还不可能。
一些不同的人知道您更笼统地描述的内容 names/terms。首先想到的是"Aspect Oriented Programming"(简称AOP)。它处理所谓的 cross cutting concerns。我敢打赌你想做两件事中的一件
- 以标准化有意义的方式记录 exceptions/messages
- 记录 times/performance 系统区域
从一般意义上讲,是的,C# 能够做这样的事情。网上会有无数的教程教你如何做,这样回答太笼统了。
然而,asp.netMVC 的作者对这些事情深思熟虑,并为您提供了许多如您所描述的属性,可以根据需要进行扩展,并提供对管道的轻松访问向开发人员提供他们需要的所有信息(例如当前路由、任何参数、任何异常、任何 authorization/authentication 请求等)
这将是一个很好的起点:http://www.strathweb.com/2015/06/action-filters-service-filters-type-filters-asp-net-5-mvc-6/
这看起来也不错:http://www.dotnetcurry.com/aspnet-mvc/976/aspnet-mvc-custom-action-filter
属性在您描述的场景中起作用的原因是因为其他代码负责实际调用方法或读取属性,而其他代码将查找属性并相应地修改行为。当您只是 运行 C# 代码时,您通常不会得到它;没有一种本地方法可以在执行方法之前执行属性中的代码。
从您的描述来看,您似乎在追求面向方面的编程。有关框架列表,请参阅 What is the best implementation for AOP in .Net?。
本质上,使用适当的 AOP 框架,您可以添加属性或其他标记,并在编译时执行或插入代码。有很多方法,因此我不是很具体,抱歉。 您确实需要了解 AOP 方法不同于 ASP.Net MVC 之类的方法,因为 AOP 通常会修改您的运行时代码(无论如何在我的理解中,我确信它也有变化)。
至于 AOP 是否真的可行将取决于您的要求,但我会谨慎行事 - 这不适合胆小的人。
此问题的一个完全替代解决方案是查看类似 Mediatr 或类似的东西,将您的逻辑分解为一组命令,您可以通过消息总线调用这些命令。有用的原因是您可以使用各种类型的逻辑(包括授权逻辑)装饰您的消息总线(或管道)。该解决方案与您要求的非常不同 - 但无论如何可能更可取。
或者只是将单行授权调用添加为每个方法中的第一行,而不是将其作为属性...