如果找不到名称,统一容器是否可以解析默认类型?

时间:2016-07-20 10:46:06

标签: c# .net unity-container

是否可以两次注册相同的接口,其中第一个解析为默认实现,第二个具有名称并解析为另一个类型。

示例:

container.RegisterType(typeof(IMyInterface), typeof(MyDefaultImplementation));
container.RegisterType(typeof(IMyInterface), typeof(MySecondImplementation),"Second Implementations name");

所以,

Resolve<IMyInterface>("non existing name")

应解决MyDefaultImplementation。

2 个答案:

答案 0 :(得分:3)

如果你可以使用容器,你可以做一个扩展方法:

public static class UnityExtensions
{
    public static T TryResolve<T>(this IUnityContainer container, string name)
    {
        if (container.IsRegistered<T>(name))
            return container.Resolve<T>(name);

        return container.Resolve<T>();
    }
}

并使用它:

container.RegisterType<IMyInterface, Foo>();
container.RegisterType<IMyInterface, Bar>("bar");

var foo = container.TryResolve<IMyInterface>("non-existing");
// foo will be Foo
var bar = container.TryResolve<IMyInterface>("bar");
// bar will be Bar.

public interface IMyInterface { }
public class Foo : IMyInterface { }
public class Bar : IMyInterface { }

缺点是您需要知道何时使用扩展程序以及何时不使用...否则您可以构建自己的BuilderStrategy

深受影响:

Unity - loadConfiguration, how to resolve only those configured

Is there TryResolve in Unity?

答案 1 :(得分:2)

我对团结不够熟悉,但你开始创建自己的配置,将其添加为扩展名:

public class DefaultRegistrationFallbackConfiguration : UnityContainerExtension
{
    protected override void Initialize()
    {
        this.Context.Registering += this.AppendRemapPolicy;
    }

    public override void Remove()
    {
        this.Context.Registering -= this.AppendRemapPolicy;
    }

    private void AppendRemapPolicy(object sender, RegisterEventArgs e)
    {
        if (e.Name != null)
            return;

        if (e.TypeFrom != null && e.TypeTo != null)
            this.Context.Policies.SetDefault<IBuildKeyMappingPolicy>(new MapBuildKeyToDefaultPolicy(e.TypeFrom, e.TypeTo));

        if (e.LifetimeManager == null)
            return;

        throw new NotImplementedException("TODO: lifetime management");
    }
}

创建自己的IBuildKeyMappingPolicy

public class MapBuildKeyToDefaultPolicy : IBuildKeyMappingPolicy
{
    private readonly Type _typeFrom;
    private readonly Type _typeTo;

    public MapBuildKeyToDefaultPolicy(Type typeFrom, Type typeTo)
    {
        this._typeFrom = typeFrom;
        this._typeTo = typeTo;
    }

    public NamedTypeBuildKey Map(NamedTypeBuildKey buildKey, IBuilderContext context)
    {
        if (buildKey.Type == this._typeFrom)
            return new NamedTypeBuildKey(this._typeTo);

        throw new InvalidOperationException();
    }
}

测试类:

public interface IFoo
{
    void Bar();
}

public class FooNamed : IFoo
{
    public void Bar()
    {
        Console.WriteLine("named one");
    }
}

public class FooDefault : IFoo
{
    public void Bar()
    {
        Console.WriteLine("default one");
    }
}

测试:

public static class Program
{
    static void Main(string[] args)
    {
        var container = new UnityContainer();

        // register extension before use container!
        container.AddExtension(new DefaultRegistrationFallbackConfiguration());

        container.RegisterType(typeof(IFoo), typeof(FooDefault));
        container.RegisterType(typeof(IFoo), typeof(FooNamed), "named");

        container.Resolve<IFoo>()         .Bar(); // default one
        container.Resolve<IFoo>("named")  .Bar(); // named one
        container.Resolve<IFoo>("unknown").Bar(); // default one
    }
}

输出:

  

默认一个   命名为一   默认一个