我正在尝试使用Unity对一些交叉类进行依赖注入。现在我有一些缓存基础设施,我已经围绕MS企业库。我正在包装它,因为我可能想稍后使用其他东西。此外,我可能想要混合和匹配不同的缓存存储。
所以我有一个通用的缓存接口和具体实现如下
public interface ICacheProvider
{
void Add(object key, object value);
void Remove(object key);
object GetData(object key);
void Flush();
}
public class MyCacheProvider : ICacheProvider
{
private ICacheManager cacheManager;
public MyProvider(ICacheManager manager)
{
cacheManager = manager;
}
}
ICacheManager属于企业库中的类型。我要做的是使用unity来在运行时解析缓存管理器。此外,对于不同的缓存商店,这可能会有所不同。现在,他们都解析为我显示的类型。这是我的统一配置。
<unity>
<typeAliases>
<typeAlias alias="string" type="System.String, mscorlib" />
<typeAlias alias="ICacheProvider" type="DomainBase.Caching.ICacheProvider, DomainBase" />
<typeAlias alias="MSCacheProvider" type="Caching.MyCacheProvider, Caching" />
</typeAliases>
<containers>
<container>
<types>
<register type="ICacheProvider" mapTo="MSCacheProvider" />
</types>
</container>
</containers>
以下是我设置Unity容器的方法:
private IUnityContainer rootContainer;
rootContainer = new UnityContainer().LoadConfiguration();
var configurator = new UnityContainerConfigurator(rootContainer);
EnterpriseLibraryContainer.ConfigureContainer(configurator, ConfigurationSourceFactory.Create());
这允许企业库自动从配置中获取信息并根据其中的内容进行解析。问题是,当我深入两级时(即 - 我没有直接解析到企业库接口),解决方案失败,因为我没有命名解析。根据企业库扩展,不需要命名解析,因为提供的扩展注册了正确的解析,就好像它被命名一样。虽然,我收集Unity无法通过将我的界面映射到企业库来实现它的神奇飞跃。这是一些示例代码
//note that's ICacheProvider which my interface for abstracting caching. NOT
//the enterprise library interface
ICacheProvider customersCache = rootContainer.Resolve<ICacheProvider>(); //works
ICacheProvider productsCache = rootContainer.Resolve<ICacheProvider>("ProductsCache"); //doesn't work
第一个样本有效,因为有默认分辨率,但第二个样本失败,因为我没有“产品”的命名分辨率。有没有办法处理这种情况?我不想为我添加到系统的每个不同的缓存存储都有命名解析,因为它们已经在缓存配置中定义。我会尝试不同类型的注入,但在这种情况下你几乎必须使用构造函数注入。
此外,我已经尝试显式定义命名注册,我仍然获得相同的CacheManager实例,即使定义了两个单独的。我想一旦初始分辨率完成,它会查看构造函数并且没有“名称”,只是根据默认值注入?
感谢您的帮助
答案 0 :(得分:1)
找到我自己的问题的答案。我能弄清楚的唯一方法是使用自定义扩展并检查类型。这是一个样本
public class WrappedResolver : UnityContainerExtension
{
protected override void Initialize()
{
this.Context.Strategies.Add(new WrappedBuilder(this.Container), Microsoft.Practices.Unity.ObjectBuilder.UnityBuildStage.PreCreation);
}
}
public class WrappedBuilder : BuilderStrategy
{
IUnityContainer baseContainer;
public WrappedBuilder(IUnityContainer container)
{
baseContainer = container;
}
public override void PreBuildUp(IBuilderContext context)
{
if (context.BuildKey.Type.Name.Contains("ICacheProvider") && context.OriginalBuildKey.Name != null)
{
string originalName = context.OriginalBuildKey.Name;
Type mytype = Type.GetType("Microsoft.Practices.EnterpriseLibrary.Caching.ICacheManager, Microsoft.Practices.EnterpriseLibrary.Caching");
Type originalType = context.BuildKey.Type;// Type.GetType("DomainBase.Caching.ICacheProvider, DomainBase");
context.Existing = baseContainer.Resolve(originalType, new ParameterOverride("manager",
new ResolvedParameter(mytype, originalName)));
context.BuildComplete = true;
}
base.PreBuildUp(context);
}
}