Есть способ использовать WindowsAPI.
$src = @"
[DllImport("KERNEL32.DLL")]
public static extern uint GetPrivateProfileString(string lpAppName, string lpKeyName, string lpDefault, System.Text.StringBuilder lpReturnedString, uint nSize, string lpFileName);
[DllImport("KERNEL32.DLL")]
public static extern uint WritePrivateProfileString(string lpAppName, string lpKeyName, string lpString, string lpFileName);
"@
Add-Type -MemberDefinition $src -Namespace WinApi -Name IniFileIO -Language CSharp
Function Read-IniFile ($Path, $Section, $Key) {
$sb = [Text.StringBuilder]::new(1024)
[WinApi.IniFileIO]::GetPrivateProfileString($Section, $Key, $null, $sb, $sb.Capacity, (Convert-Path -LiteralPath $Path)) > $null
$sb.ToString()
}
Function Write-IniFile ($Path, $Section, $Key, $Value) {
[WinApi.IniFileIO]::WritePrivateProfileString($Section, $Key, $Value, (Convert-Path -LiteralPath $Path)) >$null
}
Использование заключается в следующем.
Read-IniFile -Path "C:\sample.ini" -Section "Section1" -Key "Key1"
Write-IniFile -Path "C:\sample.ini" -Section "Section2" -Key "Key2" -Value "Hello"
Это случайный код, поэтому лучше использовать код, написанный mklement0 для фактического использования. Это более надежно.
У Вас не должно даже быть доступа к репозиториям от объекта области.
Тому, что можно сделать, или позволяют, сервис дает объекту области соответствующую информацию или имеет делегата в объекте области, который установлен сервисом или в конструкторе.
public DomainObject(delegate getApplicationsByBatchID)
{
...
}
Почему бы не передать в IList<VendorApplication>
как параметр вместо VendorApplicationBatch? Код вызова для этого, по-видимому, прибыл бы из службы, которая будет иметь доступ к AppRepo. Тем путем Ваш доступ к репозиторию закончится, где он принадлежит, в то время как Ваша функция домена может остаться блаженно незнакомой о том, куда те данные прибыли из.
Я не эксперт по DDD, но я помню статью от великого Jeremy Miller, который ответил на этот самый вопрос для меня. Вы обычно хотели бы логику, связанную с Вашими объектами области - в тех объектах, но Ваш класс обслуживания будет должностное лицо методы, которые содержат эту логику. Это помогло мне продвинуть зависящую от домена логику в классы объекта и сохранить мои классы обслуживания менее большими (когда я помещал в большую логику в классах обслуживания как Вы упомянутый),
Править: Пример
Я пользуюсь библиотекой предприятия для простой проверки, таким образом, в классе объекта я установлю атрибут как так:
[StringLengthValidator(1, 100)]
public string Username {
get { return mUsername; }
set { mUsername = value; }
}
Объект наследовался базовому классу, который имеет следующий метод "IsValid", который гарантирует, что каждый объект соответствует критериям проверки
public bool IsValid()
{
mResults = new ValidationResults();
Validate(mResults);
return mResults.IsValid();
}
[SelfValidation()]
public virtual void Validate(ValidationResults results)
{
if (!object.ReferenceEquals(this.GetType(), typeof(BusinessBase<T>))) {
Validator validator = ValidationFactory.CreateValidator(this.GetType());
results.AddAllResults(validator.Validate(this));
}
//before we return the bool value, if we have any validation results map them into the
//broken rules property so the parent class can display them to the end user
if (!results.IsValid()) {
mBrokenRules = new List<BrokenRule>();
foreach (Microsoft.Practices.EnterpriseLibrary.Validation.ValidationResult result in results) {
mRule = new BrokenRule();
mRule.Message = result.Message;
mRule.PropertyName = result.Key.ToString();
mBrokenRules.Add(mRule);
}
}
}
Затем мы должны выполниться, этот метод "IsValid" в классе обслуживания сохраняют метод, как так:
public void SaveUser(User UserObject)
{
if (UserObject.IsValid()) {
mRepository.SaveUser(UserObject);
}
}
Более сложным примером мог бы быть банковский счет. Логика депозита будет жить в объекте учетной записи, но класс обслуживания назовет этот метод.
Насколько я понимаю (недостаточно информации, чтобы знать, является ли это правильным дизайном) VendorApplicationBatch должен содержать ленивый загруженный IList в объекте области, и логика должна остаться в домене.
Например (воздушный кодекс):
public class VendorApplicationBatch {
private IList<VendorApplication> Applications {get; set;};
public decimal CaculateBatchTotal()
{
if (Applications == null || Applications.Count == 0)
throw new ArgumentException("There were no applications for this batch, that shouldn't be possible");
decimal Total = 0m;
foreach (VendorApplication App in Applications)
Total += App.Amount;
return Total;
}
}
Это легко сделано с ORM как NHibernate, и я думаю, что это было бы лучшее решение.
Мне кажется, что ваш CalculateTotal является сервисом для коллекций VendorApplication's, и что возвращение коллекции VendorApplication's для Batch естественно подходит как свойство класса Batch. Таким образом, какой-нибудь другой сервис/контроллер/что бы то ни было извлекает соответствующую коллекцию VendorApplication из партии и передает ее сервису VendorApplicationTotalCalculator (или что-то в этом роде). Но это может нарушить некоторые правила агрегатного корневого сервиса DDD или что-то подобное, о чем я не знаю (новичок в DDD)
.