C# DI-关注点分离指南
我需要一些关于“分离关注点”的指导。我正在开发一个假期预订应用程序,试图提高我的DI和TDD知识,我有两个独立的存储库“Allocation”和“PublicHoliday”,它们都有自己的业务逻辑类AllocationLogic和PublicHolidayLogic AllocationLogic有一个名为CalculateWorkDays的方法,该方法计算给定范围内(分配对象的开始日期和结束日期属性)用户必须分配假日的日期 PublicHolidayLogic有一个名为PublicHolidaysForTheYear的方法,可以获取一年中所有的银行假日。我不想将此方法中的代码复制到CalculateWorkDays方法,而是想从CalculateWorkDays方法中的PublicHolidayLogic类调用它 我的问题是,在CalculateWorkdays方法中创建publicHolidayLogic类的实例,通过分配构造函数传入所需的存储库,这样可以吗?或者我应该在分配构造函数中将接口传递给publicholidaylogic 我希望是前者,但我已附上我的代码,任何帮助将不胜感激 --公众假期班C# DI-关注点分离指南,c#,dependency-injection,C#,Dependency Injection,我需要一些关于“分离关注点”的指导。我正在开发一个假期预订应用程序,试图提高我的DI和TDD知识,我有两个独立的存储库“Allocation”和“PublicHoliday”,它们都有自己的业务逻辑类AllocationLogic和PublicHolidayLogic AllocationLogic有一个名为CalculateWorkDays的方法,该方法计算给定范围内(分配对象的开始日期和结束日期属性)用户必须分配假日的日期 PublicHolidayLogic有一个名为PublicHolid
public class PublicHolidayLogic : IPublicHolidayLogic
{
private IPublicHolidayRepository _publicHolidayRepository;
public PublicHolidayLogic(IPublicHolidayRepository publicHolidayRepo)
{
_publicHolidayRepository = publicHolidayRepo;
}
public System.Collections.Generic.IEnumerable<Domain.Models.PublicHoliday>
PublicHolidaysForTheYear(int year, int countryId)
{
var returnedDates = _publicHolidayRepository.Enumerable()
.Where(t => t.StartDate.Year == year && t.CountryId == countryId).ToList();
List<Domain.Models.PublicHoliday> _result = new List<Domain.Models.PublicHoliday>();
foreach(Domain.Models.PublicHoliday p in returnedDates)
{
if (!_result.Any(t => t.Name == p.Name && t.StartDate == p.StartDate))
_result.Add(p);
}
return _result.AsEnumerable();
}
}
公共类PublicHolidayLogic:IPPublicHolidayLogic
{
私人IPublicHolidayRepository_publicHolidayRepository;
公共假日逻辑(IPPublicHolidayRepo)
{
_publicHolidayRepository=publicHolidayRepo;
}
public System.Collections.Generic.IEnumerable
新西兰公共假日(国际年,国际国家ID)
{
var returnedDates=_publichHolidayRepository.Enumerable()
.Where(t=>t.StartDate.Year==Year&&t.CountryId==CountryId).ToList();
列表_结果=新列表();
foreach(返回状态中的Domain.Models.p)
{
if(!\u result.Any(t=>t.Name==p.Name&&t.StartDate==p.StartDate))
_结果:添加(p);
}
返回_result.AsEnumerable();
}
}
--分配类
public class AllocationLogic : IAllocationLogic
{
private IAllocationRepository _allocationRepository;
private IPublicHolidayRepository _publicHolidayRepository;
public AllocationLogic(IAllocationRepository allocationRepo,
IPublicHolidayRepository publicHolidayRepository)
{
_allocationRepository = allocationRepo;
_publicHolidayRepository = publicHolidayRepository;
}
public int CalculateWorkingDays(Domain.Models.Allocation allocation)
{
//TODO A Better way of doing this would be nice.
List<DateTime> _dates = new List<DateTime>();
List<DateTime> _result = new List<DateTime>();
//Monday To Friday Only
for (DateTime i = allocation.StartDate; i <= allocation.EndDate; i = i.AddDays(1))
{
if (i.DayOfWeek != DayOfWeek.Saturday
&& i.DayOfWeek != DayOfWeek.Sunday
&& !_dates.Contains(i))
_dates.Add(i);
}
//Remove Bank Holidays
if (_publicHolidayRepository != null)
{
IEnumerable<Domain.Models.PublicHoliday> _holidays
= new PublicHolidayLogic(_publicHolidayRepository)
.PublicHolidaysForTheYear(allocation.StartDate.Year, allocation.User.CountryId);
if (_holidays.Count() > 0)
{
foreach (DateTime d in _dates)
{
if (!_holidays.Any(t => t.StartDate == d))
{
_result.Add(d);
}
}
}
else
{
_result.AddRange(_dates);
}
}
else
{
_result.AddRange(_dates);
}
return _result.Count;
}
}
公共类分配逻辑:IALocationLogic
{
专用IAllocationRepository\u分配存储库;
私人IPublicHolidayRepository_publicHolidayRepository;
公共分配逻辑(IAllocationRepository allocationRepo,
IPPublicHolidayRepository PublicHoliday存储库)
{
_allocationRepository=allocationRepo;
_publicHolidayRepository=publicHolidayRepository;
}
公共整数计算工作日(Domain.Models.Allocation)
{
//做一个更好的方法会很好。
列表_日期=新列表();
列表_结果=新列表();
//只有星期一到星期五
for(DateTime i=allocation.StartDate;i 0)
{
foreach(日期时间为_dates)
{
如果(!\u假日。任何(t=>t.StartDate==d))
{
_结果.添加(d);
}
}
}
其他的
{
_结果。添加范围(_日期);
}
}
其他的
{
_结果。添加范围(_日期);
}
返回_result.Count;
}
}
--分配测试类
[TestClass]
public class AllocationLogicTests
{
[TestMethod]
public void CalculateWorkingDaysOnly()
{
//Holiday
var allocation = new Allocation {
StartDate = new DateTime(2013, 1, 7),
EndDate = new DateTime(2013, 1, 18)
};
var user = new User { CountryId = 1 };
var allocationLogic = new AllocationLogic(null,null);
allocation.User = user;
int result = allocationLogic.CalculateWorkingDays(allocation);
Assert.AreEqual(10, result);
}
[TestMethod]
public void CalculateWorkingDaysWithBankHoliday()
{
//Holiday
var allocation = new Allocation {
StartDate = new DateTime(2013, 1, 7),
EndDate = new DateTime(2013, 1, 18)
};
var publicHoliday = new List<PublicHoliday> {
new PublicHoliday { CountryId = 1, StartDate = new DateTime(2013, 1, 10),
Name = "My Bank Holiday" }
};
var user = new User { CountryId = 1 };
var mock = new Mock<IPublicHolidayRepository>();
mock.Setup(s => s.Enumerable()).Returns(publicHoliday.AsEnumerable());
allocation.User = user;
var allocationLogic = new AllocationLogic(null,mock.Object);
int result = allocationLogic.CalculateWorkingDays(allocation);
Assert.AreEqual(9, result);
}
}
[TestClass]
公共类分配逻辑测试
{
[测试方法]
public void calculateworkdaysonly()
{
//假日
var分配=新分配{
StartDate=新的日期时间(2013年1月7日),
EndDate=新的日期时间(2013年1月18日)
};
var user=新用户{CountryId=1};
var allocationLogic=新的allocationLogic(null,null);
分配。用户=用户;
int result=allocationLogic.CalculateWorkingDays(分配);
断言。等于(10,结果);
}
[测试方法]
public void CalculateWorkdaysWithBankHoliday()的计算工作日
{
//假日
var分配=新分配{
StartDate=新的日期时间(2013年1月7日),
EndDate=新的日期时间(2013年1月18日)
};
var publichholiday=新列表{
新公共假日{CountryId=1,StartDate=new DateTime(2013,1,10),
Name=“我的银行假日”}
};
var user=新用户{CountryId=1};
var mock=new mock();
mock.Setup(s=>s.Enumerable()).Returns(publicHoliday.AsEnumerable());
分配。用户=用户;
var allocationLogic=new allocationLogic(null,mock.Object);
int result=allocationLogic.CalculateWorkingDays(分配);
断言。等于(9,结果);
}
}
您将关注点的分离与耦合混为一谈。通过在另一个实例中创建一个实例,您将PublicHolidayLogic与AllocationLogic紧密耦合
实际上,AllocationLogic所需要的只是访问该方法。将AllocationLogic的构造函数更改为具有类型为Func
的额外参数,并将其存储在具有相同类型的私有字段中,例如名为\u publicHolidayFunc
。然后在创建这两个类的代码中,执行以下操作:
var publicHoliday = new PublicHolidayLogic(publicHolidayRepo);
var allocationLogic = new AllocationLogic(allocationRepo,
publicHolidayRepo,
publicHoliday.PublicHolidaysForTheYear);
...
最后将方法更改为:
if (_publicHolidayRepository != null)
{
var holidays = _publicHolidayFunc(allocation.StartDate.Year, allocation.User.CountryId);
if (_holidays.Count() > 0)
{
...
然后使用DI注入所需的方法,将这两个类彼此解耦。将关注点的分离与耦合混为一谈。通过在另一个实例中创建一个实例,您将PublicHolidayLogic与AllocationLogic紧密耦合 实际上,AllocationLogic所需要的只是访问该方法。将AllocationLogic的构造函数更改为具有类型为
Func
的额外参数,并将其存储在具有相同类型的私有字段中,例如名为\u publicHolidayFunc
。然后在创建这两个类的代码中,执行以下操作:
var publicHoliday = new PublicHolidayLogic(publicHolidayRepo);
var allocationLogic = new AllocationLogic(allocationRepo,
publicHolidayRepo,
publicHoliday.PublicHolidaysForTheYear);
...
最后将方法更改为:
if (_publicHolidayRepository != null)
{
var holidays = _publicHolidayFunc(allocation.StartDate.Year, allocation.User.CountryId);
if (_holidays.Count() > 0)
{
...
然后使用DI注入所需的方法,将两个类彼此分离
我的问题是,可以创作吗