我遇到自定义操作过滤器和依赖项注入问题。这是我的代码:
PageCount.cs
public class PageCount : ActionFilterAttribute
{
[Dependency]
public IVisitorService _visitorService { get; set; }
public override void OnResultExecuted(ResultExecutedContext filterContext)
{
_visitorService.AddVisitorCount();
base.OnResultExecuted(filterContext);
}
}
IVisitorService.cs
public partial interface IVisitorService
{
int GetVisitorsCount();
void AddVisitorCount();
}
VisitorService.cs
public partial class VisitorService : IVisitorService
{
private readonly IRepository<Visitor> _visitorRepository;
public VisitorService(IRepository<Visitor> visitorRepository)
{
_visitorRepository = visitorRepository;
}
public int GetVisitorsCount()
{
Visitor v = _visitorRepository.Get(1);
return v.VisitCount;
}
public void AddVisitorCount()
{
Visitor v = _visitorRepository.Get(1);
v.VisitCount += 1;
_visitorRepository.Update(v);
}
}
UnityConfig.cs
public static void RegisterComponents()
{
var container = new UnityContainer();
// identity
container.RegisterType<DbContext, ApplicationDbContext>(new HierarchicalLifetimeManager());
container.RegisterType<UserManager<ApplicationUser>>(new HierarchicalLifetimeManager());
container.RegisterType<IUserStore<ApplicationUser>, UserStore<ApplicationUser>>(new InjectionConstructor(new ApplicationDbContext()));
container.RegisterType<AccountController>(new InjectionConstructor());
container.RegisterType<IAuthenticationManager>(new InjectionFactory( o => HttpContext.Current.GetOwinContext().Authentication));
container.RegisterType(typeof(IRepository<>), typeof(Repository<>));
container.RegisterType<IGameService, GameService>();
container.RegisterType<IGenreService, GenreService>();
container.RegisterType<IVisitorService, VisitorService>();
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
UnityMvcActivator.cs
public static void Start()
{
var container = UnityConfig.GetConfiguredContainer();
FilterProviders.Providers.Remove(FilterProviders.Providers.OfType<FilterAttributeFilterProvider>().First());
FilterProviders.Providers.Add(new UnityFilterAttributeFilterProvider(container));
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
// TODO: Uncomment if you want to use PerRequestLifetimeManager
// Microsoft.Web.Infrastructure.DynamicModuleHelper.DynamicModuleUtility.RegisterModule(typeof(UnityPerRequestHttpModule));
}
错误
目前的类型, GameCommerce.Infrastructure.Services.Visitors.IVisitorService,是一个 界面,不能构造。你错过了类型映射吗?
答案 0 :(得分:3)
问题是MVC没有使用您在 UnityConfig.cs 中的RegisterTypes
方法中设置的容器。在 UnityConfig.cs 的RegisterTypes
末尾,您将DependencyResolver.Current
设置为您在方法中创建的容器,但稍后在 UnityMvcActivator中.cs ,DependencyResolver.Current
被UnityConfig.GetConfiguredContainer()
覆盖,但不包含您的注册。
我建议您使用Unity.Mvc
包提供的 UnityConfig.cs 类,而不修改RegisterTypes
方法,如下所示:
<强> UnityConfig.cs 强>
public class UnityConfig
{
#region Unity Container
private static Lazy<IUnityContainer> container = new Lazy<IUnityContainer>(() =>
{
var container = new UnityContainer();
RegisterTypes(container);
return container;
});
/// <summary>
/// Gets the configured Unity container.
/// </summary>
public static IUnityContainer GetConfiguredContainer()
{
return container.Value;
}
#endregion
/// <summary>Registers the type mappings with the Unity container.</summary>
/// <param name="container">The unity container to configure.</param>
/// <remarks>There is no need to register concrete types such as controllers or API controllers (unless you want to
/// change the defaults), as Unity allows resolving a concrete type even if it was not previously registered.</remarks>
public static void RegisterTypes(IUnityContainer container)
{
// NOTE: To load from web.config uncomment the line below. Make sure to add a Microsoft.Practices.Unity.Configuration to the using statements.
// container.LoadConfiguration();
// TODO: Register your types here
container.RegisterType<DbContext, ApplicationDbContext>(new HierarchicalLifetimeManager());
container.RegisterType<UserManager<ApplicationUser>>(new HierarchicalLifetimeManager());
container.RegisterType<IUserStore<ApplicationUser>, UserStore<ApplicationUser>>(new InjectionConstructor(new ApplicationDbContext()));
container.RegisterType<AccountController>(new InjectionConstructor());
container.RegisterType<IAuthenticationManager>(new InjectionFactory( o => HttpContext.Current.GetOwinContext().Authentication));
container.RegisterType(typeof(IRepository<>), typeof(Repository<>));
container.RegisterType<IGameService, GameService>();
container.RegisterType<IGenreService, GenreService>();
container.RegisterType<IVisitorService, VisitorService>();
}
这种方式DependencyResolver.Current
只会在 UnityMvcActivator.cs 中设置一次。
答案 1 :(得分:1)
您是否考虑过将属性划分为&#34;被动&#34;属性如本文所述?
http://blog.ploeh.dk/2014/06/13/passive-attributes/
从您的实现开始,您正在使用属性注入,因为构造函数注入不可用,因为您只能将常量和文字传递给属性。但是你真的应该使用构造函数注入,因为你的依赖是必需的,而且在没有引用IVisitorService的情况下,win不会工作。 (属性注入通常表示可选的依赖项。)
如果您按照文章中的示例进行操作,则可以创建一个很好的关注点分离,并简化您在IoC框架中遇到的问题。