这里有一个稍微不同的方法来回答你的问题。与其完全关注注册,不如考虑如何解析到正确的类型。
IDataTranslator<TFrom, TTo>
到a
DataTranslator<TFrom, TTo>
。下一步是创建Unity容器扩展,以映射特例,其中TFrom在解析时与TTo的类型相同
.
public class A { }
public class B { }
public interface IDataTranslator<TFrom, TTo>
{
TTo Translate(TFrom fromObj);
}
public class DataTranslator<TFrom, TTo> : IDataTranslator<TFrom, TTo>
{
public TTo Translate(TFrom fromObj)
{
return Activator.CreateInstance<TTo>();
}
}
public class IdentityDataTranslator<T> : IDataTranslator<T, T>
{
public T Translate(T fromObj)
{
return fromObj;
}
}
接下来,创建一个容器扩展来处理IdentityDataTranslator:
public class IdentityGenericsExtension : UnityContainerExtension
{
private readonly Type identityGenericType;
private readonly Type baseType;
public IdentityGenericsExtension(Type identityGenericType, Type baseType)
{
// Verify that Types are open generics with the correct number of arguments
// and that they are compatible (IsAssignableFrom).
this.identityGenericType = identityGenericType;
this.baseType = baseType;
}
protected override void Initialize()
{
this.Context.Strategies.Add(
new IdentityGenericsBuildUpStrategy(this.identityGenericType, this.baseType),
UnityBuildStage.TypeMapping);
}
private class IdentityGenericsBuildUpStrategy : BuilderStrategy
{
private readonly Type identityGenericType;
private readonly Type baseType;
public IdentityGenericsBuildUpStrategy(Type identityGenericType, Type baseType)
{
this.identityGenericType = identityGenericType;
this.baseType = baseType;
}
public override void PreBuildUp(IBuilderContext context)
{
if (context.OriginalBuildKey.Type.IsGenericType &&
context.OriginalBuildKey.Type.GetGenericTypeDefinition() == this.baseType)
{
// Get generic args
Type[] argTypes = context.BuildKey.Type.GetGenericArguments();
if (argTypes.Length == 2 && argTypes.Distinct().Count() == 1)
{
context.BuildKey = new NamedTypeBuildKey(
this.identityGenericType.MakeGenericType(argTypes[0]),
context.BuildKey.Name);
}
}
}
}
}
IDataTranslator<T,K>
有两个泛型参数,两个泛型参数都是同一类型。如果是这样,那么
IdentityDataTranslator<T>
DataTranslator<T,K>
最后,设置容器并运行一些测试,以确保获得
IdentityDataTranslator
var container = new UnityContainer();
container.AddExtension(
new IdentityGenericsExtension(typeof(IdentityDataTranslator<>), typeof(IDataTranslator<,>)));
container.RegisterType(typeof(IDataTranslator<,>), typeof(DataTranslator<,>));
// Since A is different than B we get back a DataTranslator<A,B>
var dataTranslator = container.Resolve<IDataTranslator<A, B>>();
Debug.Assert(dataTranslator.GetType() == typeof(DataTranslator<A, B>));
// Since A is the same as A we get back a IdentityDataTranslator<A>
var identityTranslator = container.Resolve<IDataTranslator<A, A>>();
Debug.Assert(identityTranslator.GetType() == typeof(IdentityDataTranslator<A>));
上述方法可行,但可能有一种严格基于注册的方法,我没有想到这也可行,并强制执行您的约束。