我们来看一个简单的"帐户注册"示例,这里是流程:
当然,我们可以通过读取MVC控制器中的ReadModel来验证UserName的唯一性,以提高性能和用户体验.但是,我们仍然需要在RegisterCommand中再次验证唯一性,显然,我们不应该在命令中访问ReadModel.
如果我们不使用Event Sourcing,我们可以查询域模型,这样就没问题了.但是如果我们使用Event Sourcing,我们无法查询域模型,那么我们如何验证RegisterCommand中的UserName唯一性?
注意: User类具有Id属性,UserName不是User类的键属性.在使用事件源时,我们只能通过Id获取域对象.
顺便说一句:在要求中,如果已经输入了UserName,则网站应向访问者显示错误消息"抱歉,用户名XXX不可用".显示一条消息是不可接受的,例如"我们正在创建您的帐户,请稍后,我们会通过电子邮件将注册结果发送给您"给访问者.
有任何想法吗?非常感谢!
[UPDATE]
一个更复杂的例子:
需求:
下订单时,系统应该检查客户的订购历史,如果他是一个有价值的客户(如果客户在去年每月至少订购10个订单,他是有价值的),我们会在订单上减价10%.
执行:
我们创建PlaceOrderCommand,在命令中,我们需要查询订购历史记录以查看客户端是否有价值.但是我们怎么能这样做呢?我们不应该在命令中访问ReadModel!正如Mikael 所说,我们可以在帐户注册示例中使用补偿命令,但如果我们在此订购示例中也使用补偿命令,那么它将太复杂,并且代码可能难以维护.
我对MVC模式不太熟悉.你能告诉我以下哪三种控制器动作更好吗?谢谢 :)
(1)查询在行动:
public ActionResult List()
{
var query = repository.Query().Where(it => it.IsHandled).OrderBy(it => it.Id);
// ...
}
Run Code Online (Sandbox Code Playgroud)
(2)有服务查询:
public ActionResult List()
{
var items = service.GetHandledItemsOrderById();
// ...
}
Run Code Online (Sandbox Code Playgroud)
(3)通过行动订购:
public ActionResult List()
{
var items = service.GetHandledItems().OrderBy(it => it.Id);
// ...
}
Run Code Online (Sandbox Code Playgroud)
如果我们选择(1),那么我们在控制器中有太多的业务逻辑?
如果我们选择(2),可能会有很多服务方法GetXXXByYYY().
如果我们选择(3),为什么我们封装Where(it => it.IsHandled)但不是
OrderBy(it => it.Id.
有任何想法吗?
我正在阅读"现代操作系统"一书.我对"页面大小"感到困惑.
在这本书中,作者说,
传入的16位虚拟地址分为4位页码和12位偏移量.对于页码,有4位,我们可以有16页,并且对于偏移有12位,我们可以寻址页面中的所有4096 个字节.
为什么4096字节?使用12位,我们可以在页面内处理4096个条目,这是正确的.但是,一个条目是一个地址(在这种情况下,地址大小= 16位).所以我认为我们可以解决4096(条目)*16(位)= 4096(条目)*2(字节)= 8KB,但为什么书中说我们可以解决4096(字节)?
提前致谢!:)
operating-system memory-management virtual-memory memory-mapping
我正在使用一个使用ASP.NET MVC并支持插件的Web平台.在这个平台中,每个插件都是/ Plugins文件夹下的文件夹.例如,插件A的虚拟路径是/ Plugins/PluginA.
在开发中,一个插件是一个独立的asp.net mvc Web应用程序.使插件开发更容易.我在主项目(平台)所在的同一解决方案中创建插件项目.在运行时,平台将动态加载插件项目的bin文件夹中的程序集.
问题是,每次调试主项目时,visual studio都会启动许多Web开发服务器(一个用于主项目,一个用于每个插件项目).
因此,如果我有20个插件,visual studio将启动21个开发服务器.它使我的电脑变慢.那么,如果有一种方法可以禁用插件项目的开发服务器,也就是说,让visual studio在调试时只启动一个开发服务器?
顺便说一句:我仍然需要对插件项目中的Razor视图进行智能化.
我需要在C#中抑制一个特定的编译器警告.现在我可以这样做:
#pragma warning disable 0649
private string _field;
#pragma warning restore 0649
Run Code Online (Sandbox Code Playgroud)
有没有办法像下面这样做?
[SuppressCompilerWarning("0649")]
private string _field;
Run Code Online (Sandbox Code Playgroud)
因为我只需要禁止该字段的警告,而不是代码块.
注意:我想要禁止编译器警告,而不是代码分析警告.
谢谢!
在.net框架中,有一个IEnumerable<T>继承自非泛型的通用接口IEnumerable,它们都有一个GetEnumerator()方法.这两者之间的唯一区别GetEnumerator()是返回类型.现在我有类似的设计,但是当我编译代码时,编译器说:
MyInterface<T>.GetItem()'隐藏继承成员' MyInterface.GetItem()'.如果要隐藏,请使用new关键字.
所述MyInterface<T>.GetItem()返回一个具体类型T,而MyInterface.GetItem()返回System.Object类型.
所以我认为如果BCL团队成员编译.net框架,他们会得到同样的警告.
我认为编译器警告不好,你怎么看?我该如何解决这个问题?我的意思是我想在调用MyInterface<T>.GetItem()不仅仅是System.Object类型的实例时得到具体类型T.
提前致谢!:-)
补充: 我说接口是自己的:IMyInterface 继承自 IMyInterface,它们都有GetItem()方法(IMyInterface.GetItem()返回类型T,而IMyInterface.GetItem()返回类型System.Object).问题是,如果我们的代码只有这两个接口,即没有派生的具体类,我们将在编译源代码后遇到编译器警告.
这个好的答案解释了GC在方法执行完毕之前如何收集局部变量:
当抖动将IL编译为机器代码时,抖动执行两个重要的任务.... 它还生成一个表,描述如何使用方法体内的局部变量.该表具有每个方法参数的条目和具有两个地址的局部变量.变量首先存储对象引用的地址.以及不再使用该变量的机器代码指令的地址.......表中的"不再使用"地址非常重要.它使垃圾收集器非常有效.它可以收集对象引用,即使它在方法中使用并且该方法尚未完成执行.
我很好奇JIT如何创建内部表,以及如何在真正的clr源代码中维护"不再使用"地址.有人能在最近开源的coreclr源代码中向我展示相关的代码片段吗?
看这里(抽象类设计):http://msdn.microsoft.com/en-us/library/ms229047.aspx
它说:
(1)不要在抽象类型中定义公共或受保护的内部(Visual Basic中的受保护的朋友)构造函数.
在C#中,我们无法实例化抽象类.那么,在C#中为抽象类定义公共构造函数是否仍然重要?或者因为语义含义而没有为抽象类编写公共构造函数?
它还说:
(2)在抽象类中定义受保护或内部构造函数.
定义内部构造函数?? 在(1)中,它告诉我们不定义内部受保护的构造函数是因为"具有公共或受保护的内部可见性的构造函数是针对可以实例化的类型".不为抽象类定义内部构造函数会破坏(1)中的规则吗?
提前致谢.:)
我对CQRS中的指挥部分的设计有一些想法.我想听听你对我的想法的看法.提前致谢!:)
在CQRS中,有Commands和CommandExecutors.有时我们希望命令执行程序在执行完成后返回一些结果.一种可能的解决方案是(C#):
public interface ICommandExecutor<TCommand>
{
void Execute(TCommand cmd);
}
public interface ICommandExecutor<TCommand, TResult>
{
TResult Execute(TCommand cmd);
}
Run Code Online (Sandbox Code Playgroud)
目前很好.我们使用两个命令执行器接口.现在让我们看看客户端代码:
var cmd = new MyCommand();
commandBus.Execute(cmd); // execute no result
commandBus.Execute<MyResult>(cmd); // execute result
Run Code Online (Sandbox Code Playgroud)
是的,我们现在可以让执行者返回结果.但是在编写上面的代码时,程序员可能会感到困惑:这个命令能否执行结果?为了得到答案,程序员需要查看框架源代码,看看是否有MyCommandExecutor或MyCommandExecutor.这是不好的!很混乱!
所以,在我看来,我们应该删除 ICommandExecutor<TCommand, TResult>.也就是说,我认为命令执行程序应该总是返回void.设计ICommandExecutor<TCommand, TResult>很糟糕!
如果我们需要在命令执行后查看更改的内容.我们应该在调用commandBus.Execute(cmd)后对数据库进行新的查询.
你觉得怎么样?
在我的senario中,我有一个全局设置对象,比如GlobalSettings,它有一个静态属性"Current"(单例),并且应该只有一个GlobalSettings实例.
但是......在我的数据模型中,有一个实体"LocalizedContent":
public class LocalizedContent {
public string Title { get; set; }
public string Content { get; set; }
public string CultureName { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
在构造函数中,我想通过将CultureName设置为系统的默认文化来初始化实例,并且我可以从GlobalSettings.Current.DefaultCultureName获取默认文化名称.
但是,我不想在LocalizedContent类中使用单例属性"GlobalSettings.Current",因为它会导致强耦合.所以我的问题是,在哪里设置这个默认文化名称的正确位置?
提前致谢!
.net ×4
c# ×3
asp.net-mvc ×2
cqrs ×2
clr ×1
controller ×1
ienumerable ×1
inheritance ×1
jit ×1
oop ×1
plugins ×1
singleton ×1
unique ×1