当类型名称与接口名称匹配时, Unity.AutoRegistration可以正常工作,例如,TClass
和ITClass
. 我希望接口名称不带前缀“T”,喜欢IClass
并需要它IClass
来匹配TClass
。
但是当我重命名接口时,自动注册失败。我必须匹配类型/接口名称,还是有办法满足我的需求?
当类型名称与接口名称匹配时, Unity.AutoRegistration可以正常工作,例如,TClass
和ITClass
. 我希望接口名称不带前缀“T”,喜欢IClass
并需要它IClass
来匹配TClass
。
但是当我重命名接口时,自动注册失败。我必须匹配类型/接口名称,还是有办法满足我的需求?
与作者协商后,这里是所需的代码:
UContainer
.ConfigureAutoRegistration()
.LoadAssemblyFrom(Assembly.GetEntryAssembly().Location)
.ExcludeSystemAssemblies()
.Include(If.ImplementsITypeName, Then.Register())
.Include(
type => type.GetInterfaces().Any(i => i.Name.StartsWith("I") && i.Name.Substring(1) == type.Name.Substring(1)), Then.Register())
.Include(If.ImplementsSingleInterface, Then.Register())
.ApplyAutoRegistration();
AutoRegistration 的代码已经很久没有动过了。codeplex 上的TecX 项目包含一个增强的 Unity 配置引擎,该引擎最初是 StructureMap 配置的一个端口。该引擎还支持注册约定。
默认约定之一将类注册MyService
为接口的实现IMyService
。它看起来就这么简单:
public class ImplementsIInterfaceNameConvention : IRegistrationConvention
{
public void Process(Type type, ConfigurationBuilder builder)
{
if (!type.IsConcrete())
{
return;
}
Type pluginType = FindPluginType(type);
if (pluginType != null &&
Constructor.HasConstructors(type))
{
builder.For(pluginType).Add(type).Named(type.FullName);
}
}
private static Type FindPluginType(Type concreteType)
{
string interfaceName = "I" + concreteType.Name;
Type[] interfaces = concreteType.GetInterfaces();
return Array.Find(interfaces, t => t.Name == interfaceName);
}
}
如果您需要一些自定义命名约定,那么修改上面的示例将非常容易。使用该约定来配置您的容器将如下所示:
var builder = new ConfigurationBuilder();
builder.Scan(s =>
{
s.AssembliesFromApplicationBaseDirectory();
s.With(new MyCustomConvention());
});
var container = new UnityContainer();
container.AddExtension(builder);