我正在努力将NHibernate引入我们的代码库。我想我必须使用某种DI容器,所以我可以将依赖注入我从数据库加载的实体。我选择Unity作为容器。
我正在考虑使用Unity的拦截机制为我的代码添加一个事务方面,所以我可以做以下内容:
class SomeService
{
[Transaction]
public void DoSomething(CustomerId id)
{
Customer c = CustomerRepository.LoadCustomer(id);
c.DoSomething();
}
}
并且[Transaction]
处理程序将负责创建会话和事务,提交事务(或回滚异常)等。
我担心使用这种拦截会让我几乎无处不在代码中使用Unity。如果我以这种方式介绍方面,那么我绝不能永远地调用new SomeService()
,否则我将得到一个没有交易的服务。虽然这在生产代码中是可以接受的,但在测试中似乎有太多的开销。例如,我必须转换它:
void TestMethod()
{
MockDependency dependency = new MockDependency();
dependency.SetupForTest();
var service = SomeService(dependency);
service.DoSomething();
}
进入这个:
void TestMethod()
{
unityContainer.RegisterType<MockDependency>();
unityContainer.RegisterType<IDependency, MockDependency>();
MockDependency dependency = unityContainer.Resolve<MockDependency>();
dependency.SetupForTest();
var service = unityContainer.Resolve<SomeService>();
service.DoSomething();
}
这为我正在使用的每个模拟对象添加了2行,这导致了相当多的代码(我们的测试使用了很多有状态的模拟,所以测试类有5-8模拟的情况并不少见对象,有时甚至更多。)
我不认为独立注入会对此有所帮助:我必须为我在测试中使用的每个类设置注入,因为在编写测试之后可以将方面添加到类中。
现在,如果我放弃使用拦截,我最终将会:
class SomeService
{
public void DoSomething(CustomerId id)
{
Transaction.Run(
() => {
Customer c = CustomerRepository.LoadCustomer(id);
c.DoSomething();
});
}
}
这当然不是很好,但也不是那么糟糕。
我甚至可以设置我自己的穷人的拦截:
class SomeService
{
[Transaction]
public void DoSomething(CustomerId id)
{
Interceptor.Intercept(
MethodInfo.GetCurrentMethod(),
() => {
Customer c = CustomerRepository.LoadCustomer(id);
c.DoSomething();
});
}
}
然后我的拦截器可以处理类的属性,但我仍然可以使用new
实例化该类,而不用担心失去功能。
有没有更好的方法来使用Unity拦截,这并不会强迫我总是用它来实例化我的对象?
答案 0 :(得分:0)
如果您想使用AOP但是关注Unity,那么我建议您查看PostSharp。这实现了AOP作为编译后检查,但是在运行时如何使用代码没有任何变化。
他们拥有一个免费的社区版,具有良好的功能集,以及具有显着增强功能集的专业版和企业版。