Dot-Net
如何在 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存在於載入外掛的主應用程序中。如果沒有載入 implementation 的外掛IPerson,Autofac 會因為無法解決Target的依賴關係而大發雷霆。我真的不能為此責備它。但是我知道它
Target能夠處理缺少的問題,IPerson並且很樂意得到 anull。事實上,我很確定所有依賴 an 的組件IPerson都準備好null取而代之了。那麼我怎麼能告訴 Autofac - “沒關係,親愛的,別擔心,給我一個null,好嗎?”我發現的一種方法是將預設參數添加到
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 的空引用。另一種解決方案是創建
NullPerson實現。builder.RegisterType<NullPerson>().As<IPerson>(); builder.RegisterType<Target>();當您的真實實現只再次註冊它時,它將覆蓋原始實現。
只需使用可選參數,請參見以下範例:
public class SomeClass { public SomeClass(ISomeDependency someDependency = null) { // someDependency will be null in case you've not registered that before, and will be filled whenever you register that. } }