如何在Unity中使用相同的实例注册两个不同的接口...目前我正在使用
_container.RegisterType<EventService, EventService>(new ContainerControlledLifetimeManager());
_container.RegisterInstance<IEventService>(_container.Resolve<EventService>());
_container.RegisterInstance<IEventServiceInformation>(_container.Resolve<EventService>());
Run Code Online (Sandbox Code Playgroud)
哪个有效,但看起来不太好..
所以,我认为你明白了.EventService实现了两个接口,如果我解析接口,我想要对同一个对象的引用.
克里斯
我正在使用Unity IoC容器来解析我的对象.但是,我遇到了一个问题.当我有多个构造函数时 - Unity如何知道使用哪一个?当我有一个和一个没有时,它似乎使用带参数的那个.我可以明确告诉它使用哪个构造函数吗?
具体来说,我有一个类似于以下带有两个构造函数的Person类的情况.在这种情况下,我希望IoC容器使用默认构造函数 - 没有参数 - 但它选择带参数的容器.
public class SomeValueObject
{
public SomeValueObject(string name)
{
Name = name;
}
public string Name { get; set; }
}
public class Person
{
private string _name;
public Person()
{
_name = string.Empty;
}
public Person(SomeValueObject obj)
{
_name = obj.Name;
}
}
Run Code Online (Sandbox Code Playgroud)
这显然失败了,因为它无法创建SomeValueObject - 不知道要向其字符串参数注入什么.它给出的错误是:
解决依赖关系失败,type ="MyApp.Person",name ="".异常消息是:当前构建操作(构建密钥Build Key [MyApp.Person,null])失败:尝试调用构造函数MyApp.Person(MyApp.SomeValueObject obj)时无法解析参数obj.(策略类型BuildPlanStrategy,索引3)
集装箱登记:
Container.RegisterType<Person, Person>(new Microsoft.Practices.Unity.ContainerControlledLifetimeManager());
Run Code Online (Sandbox Code Playgroud)
并解决:
var person = Container.Resolve<Person>();
Run Code Online (Sandbox Code Playgroud) 我终于在C#中围绕IoC和DI缠绕我的头,并且正在努力解决一些问题.我正在使用Unity容器,但我认为这个问题适用范围更广.
使用IoC容器来分配实现IDisposable的实例让我感到害怕!你怎么知道你应该Dispose()?该实例可能是专门为您创建的(因此您应该Dispose()它),或者它可能是其生命周期在其他地方管理的实例(因此您最好不要).代码中没有任何内容告诉您,实际上这可能会根据配置发生变化!这对我来说似乎是致命的.
任何IoC专家都可以描述处理这种模糊性的好方法吗?
我知道类似的问题被多次询问(例如:这里,这里,这里和这里),但它是针对Unity的早期版本,其答案取决于使用的LifetimeManager类.
文件说:
Unity使用从LifetimeManager基类继承的特定类型(统称为生命周期管理器)来控制它如何存储对对象实例的引用以及容器如何处理这些实例.
好的,听起来不错所以我决定检查生命周期管理器中的构建实现.我的结论:
TransientLifetimeManager - 没有处理处理.Container仅解析实例,并且不会跟踪它.调用代码负责处理实例.ContainerControlledLifetimeManager - 处理终身经理时的实例(=处置容器时).提供在层次结构中的所有容器之间共享的单例实例.HierarchicalLifetimeManager- 从中获取行为ContainerControlledLifetimeManager.它在hiearchy(子容器)中为每个容器提供"单例"实例.ExternallyControlledLifetimeManager - 没有处理处理.正确的行为,因为容器不是实例的所有者.PerResolveLifetimeManager - 没有处理处理.它通常是相同的,TransientLifetimeManager但它允许在解析整个对象图时重用实例来进行依赖注入.PerThreadLifetimeManager - 没有处理处理,如MSDN中所述.谁负责处置?内置的实现PerThreadLifetimeManager是:
public class PerThreadLifetimeManager : LifetimeManager
{
private readonly Guid key = Guid.NewGuid();
[ThreadStatic]
private static Dictionary<Guid, object> values;
private static void EnsureValues()
{
if (values == null)
{
values = new Dictionary<Guid, object>();
}
}
public override object GetValue()
{ …Run Code Online (Sandbox Code Playgroud) 我现在在WPF中有点过时,并且有兴趣听到人们对最新版本的Prism(我之前使用过几个版本)和MVVM Light + Unity方法(我从未做过)的看法 - 体面的例子URL会很好).
我的项目将是一个很大的项目,包括由几个开发人员编写的多个模块 还有资金引入第三方控制套件,以便使用其中一个花哨的Docking/Workspace布局管理器建立一个漂亮的工作区(我知道Prism区域的一些比其他区域更好).
如果你现在从头开始一个项目,你会选择什么?为什么?有关特定推荐体系结构模式的详细信息将非常有用(例如,自动发现模块dll?注入日志记录服务?).基本上,任何想法和建议都会很好.我想进行一次很好的讨论.也许完全有另一个方向你建议进去?我非常处于研究阶段,并希望尽可能多的输入.
我把它放在这里因为我认为它会比Prism/MVVM Light论坛获得更少的偏见,但是,如果有更适合这个问题的地方,请指出我的方向.
Unity可以自动解决IEnumerable<T>吗?
假设我有一个带有这个构造函数的类:
public CoalescingParserSelector(IEnumerable<IParserBuilder> parserBuilders)
Run Code Online (Sandbox Code Playgroud)
我在容器中配置单个IParserBuilder实例:
container.RegisterType<IParserSelector, CoalescingParserSelector>();
container.RegisterType<IParserBuilder, HelpParserBuilder>();
container.RegisterType<IParserBuilder, SomeOtherParserBuilder>();
Run Code Online (Sandbox Code Playgroud)
我可以在不必实现自定义实现的情况下完成这项工作IEnumerable<IParserBuilder>吗?
var selector = container.Resolve<IParserSelector>();
Run Code Online (Sandbox Code Playgroud)
到目前为止,我还没有以任何简单的方式表达这一点,但我仍然在提升Unity,所以我可能错过了一些东西.
这篇来自David Haydn的有用文章(编辑:删除了骗局链接,可能是本文)展示了如何使用InjectionConstructor该类来帮助您使用Unity的装饰器模式来设置链.但是,如果装饰器链中的项目在其构造函数中具有其他参数,则InjectionConstructor必须显式声明它们中的每一个(或者Unity将抱怨它找不到正确的构造函数).这意味着您不能简单地将新的构造函数参数添加到装饰器链中的项目,而无需更新Unity配置代码.
这里有一些示例代码来解释我的意思.所述ProductRepository类首先被缠绕CachingProductRepository,然后通过LoggingProductRepostiory.除了在构造函数中使用IProductRepository之外,CachingProductRepository和LoggingProductRepository都需要来自容器的其他接口.
public class Product
{
public int Id;
public string Name;
}
public interface IDatabaseConnection { }
public interface ICacheProvider
{
object GetFromCache(string key);
void AddToCache(string key, object value);
}
public interface ILogger
{
void Log(string message, params object[] args);
}
public interface IProductRepository
{
Product GetById(int id);
}
class ProductRepository : IProductRepository
{
public ProductRepository(IDatabaseConnection db)
{
}
public Product GetById(int id)
{
return new …Run Code Online (Sandbox Code Playgroud) 如何将依赖项注入global.asax.cs,即MvcApplication类?
以前使用服务定位器(反)模式进行依赖注入,我试图通过使用IOC容器(特别是Unity.Mvc3,因为它附带了IDependencyResolver的实现)来遵循我最新的MVC应用程序中的最佳实践建议.框)和构造函数注入.
到目前为止,一切似乎都非常直接,除了一些障碍,其中一个在global.asax.cs中(另一个是自定义属性,但在SO上覆盖了这个问题).
MvcApplication类中的HttpApplication事件处理程序,例如:
Application_Start()
Application_EndRequest(object sender, EventArgs e)
Application_AcquireRequestState(object sender, EventArgs e)
Run Code Online (Sandbox Code Playgroud)
可能需要外部依赖,例如依赖ILogService.那么如何在不借助例如服务定位器(反)模式的情况下注入它们
private static ILogService LogService
{
get
{
return DependencyResolver.Current.GetService<ILogService>();
}
}
Run Code Online (Sandbox Code Playgroud)
任何帮助/建议非常感谢!
在我的工作中,我们使用Moq进行模拟,使用Unity作为IOC容器.我对此很新,并且没有很多资源可以帮助我确定我应该使用的最佳实践.
现在,我有一组特定进程需要用来完成其工作的存储库接口(例如:IRepository1,IRepository2 ... IRepository4).
在实际代码中,我可以使用IOC容器并使用RegisterType()方法确定所有IRepository对象.
我试图找出能够测试需要4个提到的存储库的方法的最佳方法.
我想我可以只注册一个Unity IOC容器的新实例,并在每个模拟对象的容器上调用RegisterInstance,为每个模拟对象传递Mock.Object值.我试图使这个注册过程可重用,所以除了单元测试需要从存储库返回一些特定数据之外,我不必一遍又一遍地对每个单元测试做同样的事情.这就是问题所在......在模拟存储库上设置期望值的最佳做法是什么?好像我只是在Unity容器上调用RegisterType,我将失去对实际Mock对象的引用,并且无法覆盖行为.
给定一个带有几个构造函数的类 - 如何告诉Resolve使用哪个构造函数?
请考虑以下示例类:
public class Foo
{
public Foo() { }
public Foo(IBar bar)
{
Bar = bar;
}
public Foo(string name, IBar bar)
{
Bar = bar;
Name = name;
}
public IBar Bar { get; set; }
public string Name { get; set; }
}
Run Code Online (Sandbox Code Playgroud)
如果我想使用Resolve创建一个Foo类型的对象,Resolve将如何知道要使用哪个构造函数?我怎么能告诉它使用正确的呢?假设我有一个注册了IBar的容器 - 它会理解它应该支持构建者采用IBar吗?如果我也指定了一个字符串 - 它会使用(string, IBar)构造函数吗?
Foo foo = unityContainer.Resolve<Foo>();
Run Code Online (Sandbox Code Playgroud)
请忽略这样一个事实:如果类只有一个构造函数可能会更容易...
unity-container ×10
c# ×7
.net ×5
idisposable ×2
decorator ×1
ienumerable ×1
moq ×1
mvvm-light ×1
prism ×1
resolve ×1