Autofac - 抽象通用类型的返回混凝土类型

时间:2013-08-16 12:21:29

标签: c# exception autofac

我正在尝试使用nice example提供的Steven为我的MVC Web应用程序实现异常处理,作为StackOverFlow问题的答案。

在底部,提供了Ninject所需的配置,以便控制器可以启动并运行。我正在使用Autofac作为IoC容器。任何有关定义控制器以实例化服务类的帮助都将受到高度赞赏。另外,如果我们不使用任何IoC容器,我会有兴趣看到如何从控制器调用服务类的示例。

更新: 继Steven的例子之后,这些是我到目前为止可以编​​写的类:

商业服务 - 层:

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配置它,那将会很棒。非常感谢提前!

1 个答案:

答案 0 :(得分:0)

在努力寻找将Steven的解决方案与Autofac集成的方法之后,我遇到了Patrick Desjardin的博客文章:

The three layers of validation(控制器,服务和存储库)。

我发现这很容易,因为您不必注入任何验证提供程序。此外,它很容易与任何层集成。请确保您也阅读了后续帖子:

How to validate model object with Asp.Net MVC correctly

Model validation and Entity Framework 4.3

任何比较两种解决方案的意见都将非常感激。非常感谢!