我目前正在构建一个Web应用程序,并尝试按照良好的MVC和面向服务的体系结构进行设计.
但是,我在连接表示层(即我的控制器)和后端服务时遇到了一些障碍,同时仍然保持良好的错误/验证报告给用户.
我在这里阅读了一篇非常好的SO帖子,关于如何将验证逻辑与服务层分开,并且大部分都是有意义的.然而,有一个"缺陷",如果你可以称之为,在这个模型中,我嘻嘻哈哈:在查找验证器和服务所需的对象时,如何避免重复工作?
我认为用一个相当简单的例子解释会更容易:
假设我有一个允许用户共享代码片段的应用程序.现在,我决定添加一项新功能,允许用户将他们的GitHub帐户附加到我的网站上的帐户(即建立个人资料).出于这个例子的目的,我将简单地假设我的所有用户都是值得信赖的,并且只会尝试添加他们自己的GitHub帐户,而不是其他人的:)
按照前面提到的SO文章,我已经设置了一个基本的GitHub服务来检索GitHub用户信息.
interface IGitHubUserService {
GitHubUser FindByUserName(string username);
}
Run Code Online (Sandbox Code Playgroud)
GitHubUserService的具体实现会进行昂贵的调用以https://api.github.com/users/{0}获取用户信息.再次,按照文章的模型,我实现了以下命令将用户帐户链接到GitHub用户:
// Command for linking a GitHub account to an internal user account
public class GitHubLinkCommand {
public int UserId { get; set; }
public string GitHubUsername { get; set }
};
Run Code Online (Sandbox Code Playgroud)
我的验证者需要验证用户输入的用户名是否是有效的GitHub帐户.这是非常简单的:调用FindByUserName上GitHubUserService,并确保结果不为空:
public sealed class GitHubLinkCommandValidator : Validator<GitHubLinkCommand> {
private readonly IGitHubUserService _userService;
public GitHubLinkCommandValidator(IGitHubUserService userService) {
this._userService = userService;
}
protected override IEnumerable<ValidationResult> Validate(GitHubLinkCommand command) …Run Code Online (Sandbox Code Playgroud) 今天我遇到解析Windows可移植可执行文件结构的时候遇到了一个非常奇怪的问题.具体在Export表中.
在尝试解析DLL中导出函数的函数地址时,我发现自己得到了Stack Overflow(所以这看起来像是最合适的QA板).
我编写了自己的版本,GetProcAddress手动解析而不是调用现有GetProcAddress方法.请不要只是告诉我要使用现有的GetProcAddress方法,它不适合我目前的状况,我想了解这个东西.
对于我遇到的大多数情况,我的版本工作得非常好,并没有遇到任何问题.但是,该函数是针对名为API-MS-Win-Core-ProcessThreads-L1-1-0.dll(作为递归解析的一部分)的DLL进行测试的Kernel32.dll,这是StackOverflow发生的时间.
我把它缩小到以下函数导出API-MS-Win-Core-ProcessThreads-L1-1-0.dll:
CreateRemoteThreadEx
Run Code Online (Sandbox Code Playgroud)
现在,此导出的函数实际上是转发导出.通常这不用担心; 我编写了我的函数,以便它应该处理转发的导出.但是此功能转发给
api-ms-win-core-processthreads-l1-1-0.CreateRemoteThreadEx
有人在这看到问题吗?逐句通过代码,我的GetProcAddress函数然后调用LoadLibrary上api-ms-win-core-processthreads-l1-1-0,然后尝试递归查找CreateRemoteThreadEx.然而,在下一次迭代中,该CreateRemoteThreadEx函数再次转发到...
api-ms-win-core-processthreads-l1-1-0.CreateRemoteThreadEx
然后开始StackOverflow.经过一番调查后我发现了调用的结果
LoadLibraryA("api-ms-win-core-processthreads-l1-1-0");
Run Code Online (Sandbox Code Playgroud)
返回与之相同的结果
LoadLibraryA("kernel32.dll");
Run Code Online (Sandbox Code Playgroud)
我很难过.
这是我目前的代码:
#include <Windows.h>
#define MKPTR(p1,p2) ((DWORD_PTR)(p1) + (DWORD_PTR)(p2))
INT LookupExport(IMAGE_DOS_HEADER* pDosHd, DWORD* pNames, DWORD nNames, LPCSTR lpProcName)
{
// Do a binary search on the name pointer table
INT start = 0,
index = -1,
middle = -1,
end = nNames …Run Code Online (Sandbox Code Playgroud) 好吧,今天我遇到了一个奇怪的问题.我刚才写了自己的GetProcAddress版本来获取远程进程的函数地址.我显然花了很多时间阅读PE架构,找出解决这个问题的最佳方法.
根据PECOFF v8规范(我认为它是最新的官方规范),有以下符号Export Name Pointer Table:
导出名称指针表是导出名称表中的地址数组(RVAs).指针各32位,并且相对于图像库.指针是词法排序的,以允许二进制搜索.
所以我在编写GetProcAddress版本时考虑到了这一点.显然,使用线性搜索的二进制搜索,在导出表格中可以有很好的效率提升... KERNEL32.dll(1300+导出函数).
直到今天,我遇到了一个奇怪的问题.看起来Kernel32中的一些导出函数实际上并没有按词汇顺序排序,这就是我的二进制搜索.以下是使用我将在下面发布的函数导出的Dll转储的摘录:
Ordinal: 810 Name: K32QueryWorkingSetEx
Ordinal: 811 Name: LCIDToLocaleName
Ordinal: 812 Name: LCMapStringA
Ordinal: 813 Name: LCMapStringEx
Ordinal: 814 Name: LCMapStringW
Ordinal: 815 Name: LZClose
Ordinal: 816 Name: LZCloseFile
Ordinal: 817 Name: LZCopy
Ordinal: 818 Name: LZCreateFileW
Ordinal: 819 Name: LZDone
Ordinal: 820 Name: LZInit
Ordinal: 821 Name: LZOpenFileA
Ordinal: 822 Name: LZOpenFileW
Ordinal: 823 Name: LZRead
Ordinal: 824 Name: LZSeek
Ordinal: 825 Name: LZStart
Ordinal: 826 Name: LeaveCriticalSection …Run Code Online (Sandbox Code Playgroud) 首先可能需要一些上下文,
基本上我在过去几年里一直在使用VS2008 Express版本.使用快速版本(C++除外),默认情况下,在创建新项目时,项目文件都存储在临时目录中.当您第一次选择"全部保存"时,VS会提示输入项目目录,然后您可以将项目保存到常规项目目录中.
这是我发现非常有用的行为,因为很多时候我创建了非常快速,简单的程序,在我再也不需要它们之前为我做一件事.一旦我关闭VS,它会提示我是否要保存项目,我选择"丢弃"并且一切都很好; 我的项目目录不会被一次性项目的无用目录弄得乱七八糟,每个人都赢了.
然而,随着VS2010最终我注意到,默认行为已发生变化,所有新项目都直接创建到我的项目目录(是的,我知道创建项目时,我可以更改目录,但这是时间的不必要的浪费) .这使我每次想写一个小程序时都会回复表达版本,这在家里并不算太差,但在工作中我们只有VS2010专业版.每次我创建一个简单的项目时,我都要记得以后删除该目录或者面对"WindowsFormsApplication1000232131231"目录.
所以我的问题是:是否有可能改变VS2010 Profession/Ultimate的默认项目创建行为以匹配早期的2008 Express版本?
干杯,J