Unity - 基于泛型解决依赖
Unity - Resolve dependency based on generic type
我有一个名为 DocumentRepository<T>
的 class
带构造函数
DocumentDbRepository(IDocumentCollectionName collectionName)
其中IDocumentCollectionName可以是
CollectionNameFromClassName<T>
或
CollectionNameFromString
我正在通过
解决这个问题
container.RegisterType(typeof(IDocumentDbRepository<ClassA>), typeof(DocumentDbRepository<ClassA>))
container.RegisterType(typeof(IDocumentDbRepository<ClassB>), typeof(DocumentDbRepository<ClassB>))
到目前为止一切顺利。
但现在我想根据通用类型将 IDocumentCollectionName 解析为 CollectionNameFromClassName
或 CollectionNameFromString
。
所以如果我有 ClassA
,我希望 IDocumentCollectionName 解析为 CollectionNameFromClassName<ClassA>
如果我有 ClassB,我希望 IDocumentCollectionName 解析为 CollectionNameFromString
,字符串参数值
根据 this answer,这可能有效:
container.RegisterType<IDocumentCollectionName, CollectionNameFromClassName<ClassA>>("ForClassA");
container.RegisterType<IDocumentCollectionName, CollectionNameFromString>("ForClassB");
container.RegisterType<IDocumentDbRepository<ClassA>, DocumentDbRepository<ClassA>>(new InjectionConstructor(new ResolvedParameter<IDocumentCollectionName>("ForClassA")));
container.RegisterType<IDocumentDbRepository<ClassB>, DocumentDbRepository<ClassB>>(new InjectionConstructor(new ResolvedParameter<IDocumentCollectionName>("ForClassB")));
编辑: 如果您担心易失性,我可以向您建议:
首先,您创建一个函数来执行类似于您的工厂的操作:
void RegisterDocumentDbRepository<TRepository, TCollection>(ContainerType container)
{
container.RegisterType<IDocumentCollectionName, TCollection>(typeof(TRepository).Name);
var constructor = new InjectionConstructor(new ResolvedParameter<IDocumentCollectionName>(typeof(TRepository).Name));
container.RegisterType<IDocumentDbRepository<TRepository>, DocumentDbRepository<TRepository>>(constructor);
}
然后,你像这样注册你的类型:
RegisterDocumentDbRepository<ClassA, CollectionNameFromClassName<ClassA>>(container);
RegisterDocumentDbRepository<ClassB, CollectionNameFromString>(container);
我在这里找到了答案
Unity register generic type for non generic interface
结束代码看起来像
container.RegisterInstance<Func<Type, IDocumentCollectionName>>(type =>
{
if (type == typeof(ClassA))
return
(IDocumentCollectionName)
container.Resolve(typeof(CollectionNameFromClassName<>).MakeGenericType(type));
else
return (IDocumentCollectionName)
container.Resolve(typeof(CollectionNameFromString));
});
当然这意味着我必须改变我的
DocumentDbRepository(IDocumentCollectionName collectionName)
至
Func<Type, IDocumentCollectionName> collectionName
并将其解析为
collectionName(typeof(T))
我有一个名为 DocumentRepository<T>
的 class
带构造函数
DocumentDbRepository(IDocumentCollectionName collectionName)
其中IDocumentCollectionName可以是
CollectionNameFromClassName<T>
或
CollectionNameFromString
我正在通过
解决这个问题container.RegisterType(typeof(IDocumentDbRepository<ClassA>), typeof(DocumentDbRepository<ClassA>))
container.RegisterType(typeof(IDocumentDbRepository<ClassB>), typeof(DocumentDbRepository<ClassB>))
到目前为止一切顺利。
但现在我想根据通用类型将 IDocumentCollectionName 解析为 CollectionNameFromClassName
或 CollectionNameFromString
。
所以如果我有 ClassA
,我希望 IDocumentCollectionName 解析为 CollectionNameFromClassName<ClassA>
如果我有 ClassB,我希望 IDocumentCollectionName 解析为 CollectionNameFromString
,字符串参数值
根据 this answer,这可能有效:
container.RegisterType<IDocumentCollectionName, CollectionNameFromClassName<ClassA>>("ForClassA");
container.RegisterType<IDocumentCollectionName, CollectionNameFromString>("ForClassB");
container.RegisterType<IDocumentDbRepository<ClassA>, DocumentDbRepository<ClassA>>(new InjectionConstructor(new ResolvedParameter<IDocumentCollectionName>("ForClassA")));
container.RegisterType<IDocumentDbRepository<ClassB>, DocumentDbRepository<ClassB>>(new InjectionConstructor(new ResolvedParameter<IDocumentCollectionName>("ForClassB")));
编辑: 如果您担心易失性,我可以向您建议:
首先,您创建一个函数来执行类似于您的工厂的操作:
void RegisterDocumentDbRepository<TRepository, TCollection>(ContainerType container)
{
container.RegisterType<IDocumentCollectionName, TCollection>(typeof(TRepository).Name);
var constructor = new InjectionConstructor(new ResolvedParameter<IDocumentCollectionName>(typeof(TRepository).Name));
container.RegisterType<IDocumentDbRepository<TRepository>, DocumentDbRepository<TRepository>>(constructor);
}
然后,你像这样注册你的类型:
RegisterDocumentDbRepository<ClassA, CollectionNameFromClassName<ClassA>>(container);
RegisterDocumentDbRepository<ClassB, CollectionNameFromString>(container);
我在这里找到了答案 Unity register generic type for non generic interface
结束代码看起来像
container.RegisterInstance<Func<Type, IDocumentCollectionName>>(type =>
{
if (type == typeof(ClassA))
return
(IDocumentCollectionName)
container.Resolve(typeof(CollectionNameFromClassName<>).MakeGenericType(type));
else
return (IDocumentCollectionName)
container.Resolve(typeof(CollectionNameFromString));
});
当然这意味着我必须改变我的
DocumentDbRepository(IDocumentCollectionName collectionName)
至
Func<Type, IDocumentCollectionName> collectionName
并将其解析为
collectionName(typeof(T))