如果我有两个具有相同接口的类,以及一个采用它的两个不同版本的构造函数 - 如何使用 Unity 容器来解决依赖关系?
这是一个简单的测试:
class Dependant
{
public Dependant(ILog dbLog, ILog fsLog)
{
foreach (var i in Enumerable.Range(1, 15))
{
if (i%3 == 0)
dbLog.Log(string.Format("{0} - going to DB", i));
else
fsLog.Log(string.Format("{0} - going to FS", i));
}
}
}
Run Code Online (Sandbox Code Playgroud)
现在,我想使用容器来解决依赖关系。我试过这个:
static void Main(string[] args)
{
var container = new UnityContainer();
container.RegisterType<ILog, DatabaseLogger>();
container.RegisterType<ILog, FileLogger>();
var dependant = container.Resolve<Dependant>();
}
Run Code Online (Sandbox Code Playgroud)
但是当使用 FileLogger 的两个实例解析 Dependent 时。我尝试为注册提供名称,以匹配构造函数使用的名称,但这不起作用。
当我开始我的项目(基于奥尔良项目)时,发现缺少引用引发了一个奇怪的警告:
[2015-07-26 20:03:06.970 GMT 6 INFO 100000 AssemblyLoader.Client ] User assembly ignored: C:\Users\Gutemberg\Documents\Visual Studio 2015\Projects\PI - Switch (MS)\PI.Switch.Gateway.Host\bin\Debug\Microsoft.Practices.Unity.dll
* An assembly dependency [Microsoft.Practices.ServiceLocation, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, Could not load file or assembly 'Microsoft.Practices.ServiceLocation, Version=1.2.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35' or one of its dependencies. The system cannot find the file specified.] could not be loaded: 0
Run Code Online (Sandbox Code Playgroud)
Microsoft.Practices.ServiceLocation 没有出现在 Unity Nuget 包中,我在任何地方都找不到它!这导致我的应用程序出现一些奇怪的运行时行为。
我正在使用 nuget 的最新 Unity。随附的屏幕截图证明了依赖关系 (ILSpy) 以及 VS 上的项目参考 + Nuget 包管理器屏幕。
这个参考真的有必要吗?我怎样才能摆脱它?
谢谢!非常感谢您的帮助。
我必须将所有 IdentityFramework 类和接口移至单独的库,这意味着新的Common.Models.Interfaces接口库只能引用其他接口库(或 .net 库)。这意味着我所有的ApplicationUser参数和变量都变成了IApplicationUser。
经过几个小时的更改后,我已经全部构建完毕,但在运行时我收到以下错误:
当前类型 Microsoft.AspNet.Identity.IUserStore`1[Common.Models.Interfaces.Account.IApplicationUser] 是一个接口,无法构造。您是否缺少类型映射?
所以我的问题是:我可能会缺少什么类型映射?
我之前已经使用http://tech.trailmax.info/2014/09/aspnet-identity-and-ioc-container-registrationdbcontext中的以下代码解决了问题(特别是使用)InjectionConstructor
container.RegisterType<IApplicationUser, ApplicationUser>();
container.RegisterType<DbContext, ApplicationDbContext>();
container.RegisterType<IdentityDbContext<ApplicationUser>, ApplicationDbContext>();
container.RegisterType<IIdentityMessageService, EmailService>();
container.RegisterType<IApplicationSignInManager, ApplicationSignInManager>();
container.RegisterType<IUserStore<ApplicationUser>, UserStore<ApplicationUser>>(new InjectionConstructor(typeof(ApplicationDbContext)));
Run Code Online (Sandbox Code Playgroud)
注意:此处提到的其他错误已删除,因为它具有误导性。看起来我需要额外的映射,但不知道是什么。
应用程序的用户界面和类如下(已修剪),以便您可以发现我出错的地方:
public interface IApplicationUser : IUser, IUser<string>
{
...
}
Run Code Online (Sandbox Code Playgroud)
public class ApplicationUser : IdentityUser, IApplicationUser
{
...
}
Run Code Online (Sandbox Code Playgroud)
public class ApplicationDbContext : IdentityDbContext<ApplicationUser>
Run Code Online (Sandbox Code Playgroud)
显然,不可能包含所有相关代码来重现此问题,因为它运行了 1000 行,并且不需要重现,因此只有 IOC 专家才应申请。:)
在获得有用的链接后,@guillaume31我尝试了以下操作:
container.RegisterType(typeof(IUserStore<>), typeof(UserStore<>), new InjectionConstructor(typeof(ApplicationDbContext)));
Run Code Online (Sandbox Code Playgroud)
这可以编译,但我收到一个新错误:
GenericArguments[0], 'Common.Models.Interfaces.Account.IApplicationUser', on …
c# asp.net-mvc entity-framework unity-container asp.net-identity
如何在其他元素之上显示我的 ui 元素?
http://prntscr.com/brjccg您可以看到面板的右侧,但左侧位于地图对象下方。如何解决我想看到它的两面?
是否可以注册相同的接口两次,其中第一个解析为默认实现,第二个具有名称并解析为另一种类型。
例子:
container.RegisterType(typeof(IMyInterface), typeof(MyDefaultImplementation));
container.RegisterType(typeof(IMyInterface), typeof(MySecondImplementation),"Second Implementations name");
Run Code Online (Sandbox Code Playgroud)
所以,
Resolve<IMyInterface>("non existing name")
Run Code Online (Sandbox Code Playgroud)
应该解决 MyDefaultImplementation。
当我将 asp.net mvc 应用程序复制到我们测试服务器的 IIS 文件夹时,我在该应用程序上遇到以下错误。
在本地它工作得很好:
检测到尝试覆盖名称为“”的 System.Web.IHttpHandler 类型(当前映射到 Microsoft.Reporting.WebForms.HttpHandler 类型到 Microsoft.Reporting.WebForms.HttpHandler 类型)的现有映射。
UnityConfig.cs 代码是这样的:
namespace xxx.Relacionamiento.Web.App_Start
{
/// <summary>
/// Specifies the Unity configuration for the main container.
/// </summary>
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 …Run Code Online (Sandbox Code Playgroud) 我有一个从 ASP.Net Core(针对 4.5)和一个 4.5 Web 应用程序引用的类库,我想共享应用程序设置。我在 4.5 端使用 Unity 进行 DI,在 Core 端使用 Core Bootstrapping。在核心方面,我像这样注册了一种我的应用程序设置
services.Configure<AppSettings>(Configuration.GetSection("AppSettings"));
Run Code Online (Sandbox Code Playgroud)
然后我像这样引用 AppSettings
private readonly AppSettings _appSettings;
public SubmissionRepository(PricingContext dbContext, IMapper mapper, IOptions<AppSettings> appSettings)
{
_appSettings = appSettings;
}
Run Code Online (Sandbox Code Playgroud)
我想在 4.5 端注册我的服务,我能够在 WebApiConfig.cs 中使用 Unity 进行此操作
container.RegisterType<AppSettings>(new InjectionFactory(o => BuildAppSettings()));
Run Code Online (Sandbox Code Playgroud)
BuildAppSettings 只是使用 ConfigurationManager 填充该类型的实例(不确定这是否是正确的方法)
但是我在运行时遇到异常
无法将“.Core.Integration.Models.AppSettings”类型的对象转换为“Microsoft.Extensions.Options.IOptions`1[Core.Integration.Models.AppSettings]”。
我猜我需要以某种方式将 IOptions 实例放入我的容器中,但不确定如何执行此操作。有没有首选/更好的方法来做到这一点?
我想获得这里答案中描述的行为,但通过代码使用配置。代码示例显示创建的自定义属性没有任何与统一相关的内容,并通过配置添加行为。
自定义属性位于同一解决方案中引用的单独程序集中。
问题是它在配置过程中抛出异常:
InvalidOperationException:Microsoft.Practices.Unity.InterceptionExtension.CustomAttributeMatchingRule 类型没有采用参数(LogAttribute、Boolean)的构造函数。
container
.AddNewExtension<Interception>()
.Configure<Interception>()
.AddPolicy("MyLoggingPolicy")
.AddMatchingRule<CustomAttributeMatchingRule>(
new InjectionConstructor(typeof(Abstractions.Attributes.LogAttribute), true))
.AddCallHandler<LoggingHandler>(new ContainerControlledLifetimeManager())
.Interception
.Container
.RegisterType<IFirstInterface>(new InjectionFactory((context) => FirstClassFactoryMethod()))
.RegisterType<ISecondInterface>(new InjectionFactory((context) => SecondClassFactoryMethod()));
[AttributeUsage(AttributeTargets.Method)]
public class LogAttribute : Attribute { }
public class LoggingHandler : ICallHandler
{
public int Order { get; set; }
public IMethodReturn Invoke(IMethodInvocation input, GetNextHandlerDelegate getNext)
{
Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss")} Started: {input.MethodBase.Name}");
var result = getNext()(input, getNext);
Console.WriteLine($"{DateTime.Now.ToString("yyyy-MM-dd hh:mm:ss")} Completed: {input.MethodBase.Name}");
return result;
}
}
Run Code Online (Sandbox Code Playgroud)
更新抛出的行:
.AddMatchingRule(
new CustomAttributeMatchingRule(typeof(Abstractions.Attributes.LogAttribute), true))
Run Code Online (Sandbox Code Playgroud)
防止抛出异常,但 LoggingHandler 不会收到来自具有 …
我有一个带有两个构造函数参数的 FaxService 类。
public FaxService(string phone, IFaxProvider faxProvider)
Run Code Online (Sandbox Code Playgroud)
Unity 如何配置为发送第一个参数的字符串和第二个参数的 IFaxProvider 实例?我意识到我可以注入另一个提供字符串的服务,但我正在寻找一种不必更改 FaxService 构造函数参数的解决方案。
这就是我到目前为止所拥有的......
class Program
{
static void Main(string[] args)
{
var container = new UnityContainer();
var phone = "214-123-4567";
container.RegisterType<IFaxProvider, EFaxProvider>();
container.RegisterType<IFaxService, FaxService>(phone);
var fax = container.Resolve<IFaxService>();
}
}
public interface IFaxService { }
public interface IFaxProvider { }
public class FaxService : IFaxService
{
public FaxService(string phone, IFaxProvider faxProvider) { }
}
public class EFaxProvider : IFaxProvider { }
Run Code Online (Sandbox Code Playgroud)
但它抛出...
Unity.Exceptions.ResolutionFailedException HResult=0x80131500
Message=依赖关系解析失败,类型=“ConsoleApp3.IFaxService”,名称=“(无)”。while:解决时发生异常。
我在我的 .NET Core 2.1 项目上使用了Unity DI Container v5.8.4,我需要注册Mediator对象,我正在使用这里建议的配置。
现在我已经更新到v5.9.4并且我有一个关于RegisterType方法参数的错误:
无法从“Unity.Lifetime.LifetimeManager”转换为“Unity.Injection.InjectionMember”
这是我的实际代码:
public static IUnityContainer RegisterMediator(this IUnityContainer container, LifetimeManager lifetimeManager)
{
return container.RegisterType<IMediator, Mediator>(lifetimeManager)
.RegisterInstance<ServiceFactory>(type =>
{
var enumerableType = type
.GetInterfaces()
.Concat(new[] { type })
.FirstOrDefault(t => t.IsGenericType && t.GetGenericTypeDefinition() == typeof(IEnumerable<>));
return enumerableType != null
? container.ResolveAll(enumerableType.GetGenericArguments()[0])
: container.IsRegistered(type)
? container.Resolve(type)
: null;
});
}
Run Code Online (Sandbox Code Playgroud)
我该怎么做才能更新注册码?