StackOverFlow の質問への回答としてStevenが提供した素敵な例を使用して、MVC Web アプリケーションに例外処理を実装しようとしています。
下部には、コントローラーを起動して実行できるように、Ninject に必要な構成が提供されています。IoC コンテナーとして Autofac を使用しています。サービスクラスをインスタンス化するためのコントローラーを定義するための助けをいただければ幸いです。また、IoC コンテナーを使用していない場合に、コントローラーからサービス クラスを呼び出す方法の例も見てみたいと思います。
更新: スティーブンの例に続いて、これらは私がこれまでに書くことができたクラスです:
ビジネス サービス層:
namespace BusinessService.ValidationProviders
{
public interface IValidationProvider
{
void Validate(object entity);
void ValidateAll(IEnumerable entities);
}
}
namespace BusinessService.ValidationProviders
{
public interface IValidator
{
IEnumerable<ValidationResult> Validate(object entity);
}
}
namespace BusinessService.ValidationProviders
{
public class ValidationResult
{
public ValidationResult(string key, string message)
{
this.Key = key;
this.Message = message;
}
public string Key { get; private set; }
public string Message { get; private set; }
}
}
namespace BusinessService.ValidationProviders
{
public abstract class Validator<T> : IValidator
{
IEnumerable<ValidationResult> IValidator.Validate(object entity)
{
if (entity == null) throw new ArgumentNullException("entity");
return this.Validate((T)entity);
}
protected abstract IEnumerable<ValidationResult> Validate(T entity);
}
}
namespace BusinessService.ValidationProviders
{
public class ValidationProvider : IValidationProvider
{
private readonly Func<Type, IValidator> _validatorFactory;
public ValidationProvider(Func<Type, IValidator> validatorFactory)
{
this._validatorFactory = validatorFactory;
}
public void Validate(object entity)
{
var results = this._validatorFactory(entity.GetType())
.Validate(entity).ToArray();
if (results.Length > 0) throw new ValidationException(results);
}
public void ValidateAll(IEnumerable entities)
{
var results = (
from entity in entities.Cast<object>()
let validator = this._validatorFactory(entity.GetType())
from result in validator.Validate(entity)
select result).ToArray();
if (results.Length > 0) throw new ValidationException(results);
}
}
}
namespace BusinessService.ValidationProviders
{
public sealed class NullValidator<T> : Validator<T>
{
protected override IEnumerable<ValidationResult> Validate(T entity)
{
return Enumerable.Empty<ValidationResult>();
}
}
}
namespace BusinessService.ValidationProviders
{
public class ValidationException : Exception
{
public ValidationException(IEnumerable<ValidationResult> r)
: base(GetFirstErrorMessage(r))
{
this.Errors =
new ReadOnlyCollection<ValidationResult>(r.ToArray());
}
public ReadOnlyCollection<ValidationResult> Errors { get; private set; }
private static string GetFirstErrorMessage(
IEnumerable<ValidationResult> errors)
{
return errors.First().Message;
}
}
}
namespace BusinessService.ValidationProviders
{
public class NotificationValidator: Validator<NotificationViewModel>
{
protected override IEnumerable<ValidationResult> Validate(NotificationViewModel entity)
{
if (entity.PolicyNumber.Length == 0)
yield return new ValidationResult("PolicyNumber",
"PolicyNumber is required.");
if (entity.ReceivedBy.Length == 0)
yield return new ValidationResult("ReceivedBy",
"ReceivedBy is required.");
if (entity.ReceivedDate < DateTime.Now)
yield return new ValidationResult("ReceivedDate",
"ReceivedDate cannot be earlier than the current date.");
}
}
}
namespace BusinessService
{
public class NotificationService : INotificationService
{
private readonly IValidationProvider _validationProvider;
public NotificationService(IValidationProvider validationProvider)
{
this._validationProvider = validationProvider;
}
public void CreateNotification(NotificationViewModel viewModel )
{
// Do validation here...
this._validationProvider.Validate(viewModel);
// Persist the record to the repository.
}
}
}
ViewModels-レイヤー:
namespace ViewModels
{
public class NotificationViewModel
{
public int ID { get; set; }
public string PolicyNumber { get; set; }
public string ReceivedBy { get; set; }
public DateTime ReceivedDate { get; set; }
}
}
UIレイヤー:
namespace ExceptionHandling.Controllers
{
public class NotificationController : Controller
{
private INotificationService _service;
private IValidationProvider _validationProvider;
public NotificationController()
{
_validationProvider = null; // Need to instantiate this!
this._service = new NotificationService(_validationProvider);
}
public NotificationController(INotificationService service)
{
// Need to instantiate service here..
}
[HttpGet]
public ActionResult Create()
{
return View();
}
[HttpPost]
public ActionResult Create(NotificationViewModel viewModel)
{
if (ModelState.IsValid)
{
this._service.CreateNotification(viewModel);
return RedirectToAction("Index", "Home");
}
return View();
}
}
}
コントローラーから NotificationService クラスをインスタンス化するための助けを探しています。IoC には Autofac を使用しています。Autofac 用に構成する方法について、誰かが私を正しい方向に向けることができれば、それは素晴らしいことです。よろしくお願いします!