1

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 用に構成する方法について、誰かが私を正しい方向に向けることができれば、それは素晴らしいことです。よろしくお願いします!

4

1 に答える 1