当前项目:
当我将DI从AutoFac切换到Unity时,我无法将内置在样板(robots.txt,sitemap.xml)中的服务备份并运行。特别是,我无法将这些服务的Autofac条目转换为相应的Unity条目。
我的HomeController默认构造函数与默认值相同,至少对于robots.txt,我正在进行石蕊测试:
private readonly IRobotsService _robotsService;
public HomeController(IRobotsService robotsService) {
_robotsService = robotsService;
}
我的HomeController中的robots.txt方法同样是样板的默认方法:
[NoTrailingSlash]
[OutputCache(CacheProfile = CacheProfileName.RobotsText)]
[Route("robots.txt", Name = HomeControllerRoute.GetRobotsText)]
public ContentResult RobotsText() {
Trace.WriteLine($"robots.txt requested. User Agent:<{Request.Headers.Get("User-Agent")}>.");
var content = _robotsService.GetRobotsText();
return Content(content, ContentType.Text, Encoding.UTF8);
}
IRobotsService
和RobotsService
文件也是样板的默认文件 - 它们完全未经修改(除了为简洁起见删除注释):
namespace Project.Website.Services {
public interface IRobotsService {
string GetRobotsText();
}
}
namespace Project.Website.Services {
using Boilerplate.Web.Mvc;
using Constants;
using System.Text;
using System.Web.Mvc;
public sealed class RobotsService : IRobotsService {
private readonly UrlHelper _urlHelper;
public RobotsService(UrlHelper urlHelper) => _urlHelper = urlHelper;
public string GetRobotsText() {
var stringBuilder = new StringBuilder();
stringBuilder.AppendLine("user-agent: *");
stringBuilder.AppendLine("disallow: /error/");
stringBuilder.Append("sitemap: ");
// Commented out so it wouldn't trigger the sitemap, which is not active:
//stringBuilder.AppendLine(_urlHelper.AbsoluteRouteUrl(HomeControllerRoute.GetSitemapXml).TrimEnd('/'));
return stringBuilder.ToString();
}
}
}
Autofac的原始Startup.Container.cs
非常广泛,但robots.txt服务是通过以下方式注入的:
builder.RegisterType<RobotsService>().As<IRobotsService>().InstancePerRequest();
当我的UnityConfig.cs文件包含以下内容时:
container.RegisterType<RobotsService>(new TransientLifetimeManager());
我得到了
当前类型
JCI_Vernon.Website.Services.IRobotsService
是一个接口,无法构造。你错过了类型映射吗?
其中很好地告诉我,我必须包含IRobotsService,但是当我的UnityConfig文件包含以下内容时:
container.RegisterType<IRobotsService, RobotsService>(new TransientLifetimeManager());
我得到了
当前类型
System.Web.HttpContextBase
是一个抽象类,无法构造。你错过了类型映射吗?
我不确定我的错误在哪里,因为我项目中的所有其他Unity DI都是使用这两种变体之一配置的。
非常感谢任何协助。
编辑:包括我的主项目(可见网站)中的Unity文件。
UnityMvcActivator.cs:
[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(JCI_Vernon.Website.UnityMvcActivator), nameof(JCI_Vernon.Website.UnityMvcActivator.Start))]
[assembly: WebActivatorEx.ApplicationShutdownMethod(typeof(JCI_Vernon.Website.UnityMvcActivator), nameof(JCI_Vernon.Website.UnityMvcActivator.Shutdown))]
namespace JCI_Vernon.Website {
using System.Linq;
using System.Web.Mvc;
using Unity.AspNet.Mvc;
/// <summary>
/// Provides the bootstrapping for integrating Unity with ASP.NET MVC.
/// </summary>
public static class UnityMvcActivator {
/// <summary>
/// Integrates Unity when the application starts.
/// </summary>
public static void Start() {
FilterProviders.Providers.Remove(FilterProviders.Providers.OfType<FilterAttributeFilterProvider>().First());
FilterProviders.Providers.Add(new UnityFilterAttributeFilterProvider(UnityConfig.Container));
DependencyResolver.SetResolver(new UnityDependencyResolver(UnityConfig.Container));
// TODO: Uncomment if you want to use PerRequestLifetimeManager
// Microsoft.Web.Infrastructure.DynamicModuleHelper.DynamicModuleUtility.RegisterModule(typeof(UnityPerRequestHttpModule));
}
/// <summary>
/// Disposes the Unity container when the application is shut down.
/// </summary>
public static void Shutdown() {
UnityConfig.Container.Dispose();
}
}
}
UnityConfig.cs:
namespace JCI_Vernon.Website {
using Data;
using Domain;
using Identity;
using Microsoft.AspNet.Identity;
using Services;
using Store;
using System;
using System.Web;
using System.Web.Mvc;
using Unity;
using Unity.Injection;
using Unity.Lifetime;
using Unity.Mvc5;
public static class UnityConfig {
public static IUnityContainer Container { get; internal set; }
public static void RegisterComponents() {
var container = new UnityContainer();
container.RegisterType<IUnitOfWork, UnitOfWork>(new HierarchicalLifetimeManager(), new InjectionConstructor("DefaultConnection"));
container.RegisterType<IUserStore<IdentityUser, Guid>, UserStore>(new TransientLifetimeManager());
container.RegisterType<RoleStore>(new TransientLifetimeManager());
container.RegisterInstance<HttpContextBase>(new HttpContextWrapper(HttpContext.Current), new TransientLifetimeManager());
container.RegisterType<IRobotsService, RobotsService>(new Unity.AspNet.Mvc.PerRequestLifetimeManager());
//container.RegisterType<ISitemapService, SitemapService>(new InjectionConstructor());
//container.RegisterType<ISitemapPingerService, SitemapPingerService>(new InjectionConstructor());
DependencyResolver.SetResolver(new UnityDependencyResolver(container));
}
}
}
在我的UnityMvcActivator.cs
中,我有一条PerRequestLifetimeManager
行评论和取消评论每次更改,没有观察到任何差异。在没有Unity.Mvc(作为PerRequestLifetimeManager
)的UnityConfig.cs
内使用using Unity.AspNet.Mvc;
的任何尝试均失败。
更改UnityConfig.cs
以包含Unity.AspNet.Mvc
会导致大量开启:虽然我能够在没有明显智能感知错误的情况下接受PerRequestLifetimeManager
,但UnityMvcActivator.cs
突然无法解决UnityConfig.Container
顶部没有奇怪条目的UnityConfig.cs
个条目:
public static IUnityContainer Container { get; internal set; }
UnityConfig.cs
中的SetResolver需要明确说明new Unity.Mvc5.UnityDependencyResolver(container)
,以免触发智能感知混淆。
另外,运行时,发生以下错误:
无法加载文件或程序集'Unity.Abstractions,Version = 3.1.3.0,Culture = neutral,PublicKeyToken = 6d32ff45e0ccc69f'或其中一个依赖项。定位的程序集的清单定义与程序集引用不匹配。 (HRESULT异常:0x80131040)
尽管整个解决方案都是在v5.x下创建的,但为什么它试图瞄准Unity的v3.x会导致我的灰色事件无法完全崩溃。是的,我完全清理并重建了整个解决方案,以及个别项目。
编辑2:
可能会遇到一个有趣的皱纹。在云雀,我决定完全重新安装所有NuGet包,刷新各种各样的。当然,当您升级或重新安装Unity时,它会尝试覆盖您的统一文件,这就是为什么您总是需要备份UnityConfig.cs
,否则您的注册将会消失。每一个都发生在我身上。单。 ˚F##他妈的。项目。太烦人了。
所以无论如何,我做了一个完整的刷新,我的UnityConfig.cs
突然发生了重大变化。在上面之前,包括在 v5中的所有升级,但刷新为我提供了以下内容(为简洁起见删除了注释):
namespace JCI_Vernon.Website {
using System;
using Unity;
public static class UnityConfig {
#region Unity Container
private static Lazy<IUnityContainer> container =
new Lazy<IUnityContainer>(() => {
var container = new UnityContainer();
RegisterTypes(container);
return container;
});
public static IUnityContainer Container => container.Value;
#endregion
public static void RegisterTypes(IUnityContainer container) {
// TODO: Register your type's mappings here.
// container.RegisterType<IProductRepository, ProductRepository>();
}
}
}
雅,很奇怪。重大变化,不知道为什么。旧版本工作得很好,它只是在这个帖子的特定类型映射中吹出它的cookie。
另外,我必须知道如何更改Global.cs
条目以加载我的类型映射,只需使用明显的(更改UnityConfig.RegisterComponents()
,无法找到){{1 }}没有任何意义 - 我如何传入容器?
答案 0 :(得分:0)
这里有几个问题。首先,这一行:
container.RegisterType<RobotsService>(new TransientLifetimeManager());
不等于:
builder.RegisterType<RobotsService>().As<IRobotsService>().InstancePerRequest();
它应该而不是:
container.RegisterType<IRobotsService, RobotsService>(new TransientLifetimeManager());
请记住,Autofac类型映射首先使用具体类型,然后使用接口类型。这是大多数其他DI容器的落后。
最后一条错误消息表明您需要向Unity注册HttpContextBase
。您可以将HttpContext.Current
与HttpContextWrapper
一起打包。
container.RegisterInstance<HttpContextBase>(new HttpContextWrapper(HttpContext.Current), new TransientLifetimeManager());