加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

.net – 如何在AutoFac中创建可选的依赖项?

发布时间:2020-12-13 20:42:01 所属栏目:百科 来源:网络整理
导读:我有一个接口,实现和目标: public interface IPerson { public string Name { get; } }public class Person: IPerson { public string Name { get { return "John"; } } }public class Target { public Target(IPerson person) {} } 我正在使用Autofac将事
我有一个接口,实现和目标:
public interface IPerson { public string Name { get; } }
public class Person: IPerson { public string Name { get { return "John"; } } }
public class Target { public Target(IPerson person) {} }

我正在使用Autofac将事物联系在一起:

builder.RegisterType<Person>().As<IPerson>().SingleInstance();

问题是IPerson生活在一个共享程序集中,Person存在于一个插件中(可能存在也可能不存在),而Target存在于加载插件的主应用程序中.如果没有加载实现IPerson的插件,Autofac就无法解决Target的依赖关系而犹豫不决.我不能真的责怪它.

但是我知道Target能够处理缺少IPerson而且非常乐意获得null.事实上,我非常确定依赖于IPerson的所有组件都准备好取而代之.那么我怎么能告诉Autofac-“这是好的,不要担心,只要给我一个空的,好吗?”

我找到的一种方法是向Target添加一个默认参数:

public class Target { public Target(IPerson person = null) {} }

这有效,但我需要为所有需要IPerson的组件执行此操作.我可以反过来做吗?不知何故告诉Autofac“如果所有其他方法都无法解析IPerson,请返回null”?

您可以使用以下语法:
builder.RegisterType<Target>().WithParameter(TypedParameter.From<IPerson>(null));

不幸

builder.Register(c => (IPerson)null).As<IPerson>();
  // will throw : Autofac.Core.DependencyResolutionException: A delegate registered to create instances of 'ConsoleApplication17.Program+IPerson' returned null.

builder.RegisterInstance<IPerson>(null).As<IPerson>();
  // will throw : Unhandled Exception: System.ArgumentNullException: Value cannot be null.

如果您不想为每个注册添加WithParameter,则可以添加一个可以为您执行此操作的模块

public class OptionalAutowiringModule : Autofac.Module
{
    public OptionalAutowiringModule(IEnumerable<Type> optionalTypes)
    {
        this._optionalTypes = optionalTypes;
    }
    public OptionalAutowiringModule(params Type[] optionalTypes)
    {
        this._optionalTypes = optionalTypes;
    }


    private readonly IEnumerable<Type> _optionalTypes;


    protected override void AttachToComponentRegistration(IComponentRegistry componentRegistry,IComponentRegistration registration)
    {
        base.AttachToComponentRegistration(componentRegistry,registration);

        registration.Preparing += (sender,e) =>
        {
            e.Parameters = e.Parameters.Concat(new Parameter[] { new OptionalAutowiringParameter(this._optionalTypes) });
        };
    }
}
public class OptionalAutowiringParameter : Parameter
{
    public OptionalAutowiringParameter(IEnumerable<Type> optionalTypes)
    {
        this._optionalTypes = optionalTypes.ToList();
    }


    private readonly List<Type> _optionalTypes;


    public override Boolean CanSupplyValue(ParameterInfo pi,IComponentContext context,out Func<Object> valueProvider)
    {
        if (this._optionalTypes.Contains(pi.ParameterType) && !context.IsRegistered(pi.ParameterType))
        {
            valueProvider = () => null;
            return true;
        }
        else
        {
            valueProvider = null;
            return false;
        }
    }
}

然后,您所要做的就是使用可选的依赖项注册模块

builder.RegisterModule(new OptionalAutowiringModule(typeof(IPerson)));

但不是注入可能导致nullReferenceException的null引用.另一种解决方案是创建NullPerson实现.

builder.RegisterType<NullPerson>().As<IPerson>();
  builder.RegisterType<Target>();

如果您的实际实现仅重新注册,它将覆盖原始实现.

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读