[英]Why can Autofac not create this class that takes a non-generic implementation of a generic interface as a constructor parameter?
使用 Autofac 進行注射。
鑒於
interface IStateMachine<TState, TTrigger> { }
class ConcreteStateMachine : IStateMachine<MachineState, Trigger> { }
builder.RegisterType<ConcreteStateMachine>().As<IStateMachine<MachineState, Trigger>>();
class Consumer { Consumer(IStateMachine<MachineState, Trigger> machine) { } }
為什么container.Resolve<Consumer>();
失敗並出現此異常:
Unhandled exception.
Autofac.Core.DependencyResolutionException: An exception was thrown while activating Consumer.
---> Autofac.Core.DependencyResolutionException: An exception was thrown while invoking the
constructor 'Void .ctor(IStateMachine`2[MachineState,Trigger])' on type 'Consumer'.
---> System.NullReferenceException: Object reference not set to an instance of an object.
完整的代碼設計示例: Autofac和無狀態需要 nuget
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Threading.Tasks;
using Autofac;
using Stateless;
public class Program
{
public static void Main()
{
var builder = new ContainerBuilder();
builder.RegisterType<Consumer>()
.InstancePerLifetimeScope();
builder.RegisterType<ConcreteStateMachine>()
.As<IStateMachine<MachineState, Trigger>>()
.InstancePerLifetimeScope();
var container = builder.Build();
using (var scope = container.BeginLifetimeScope())
{
var consumer = scope.Resolve<Consumer>();
consumer.TurnOn();
consumer.GetData();
consumer.TurnOff();
}
}
}
public class Consumer
{
protected IStateMachine<MachineState, Trigger> Machine;
public Consumer(IStateMachine<MachineState, Trigger> machine)
{
Machine = machine;
Machine.Register(MachineState.Off, () => Debug.WriteLine("State Off"));
Machine.Register(MachineState.On, () => Debug.WriteLine("State On"));
}
public List<string> GetData()
{
if (!Machine.IsInState(MachineState.On)) throw new InvalidOperationException("Can't GetData when machine is off!");
Debug.WriteLine("Getting Data");
return new List<String> {"Data", "Data", "Data"};
}
public void TurnOn()
{
Machine.Fire(Trigger.TurnOn);
}
public void TurnOff()
{
Machine.Fire(Trigger.TurnOff);
}
}
public class ConcreteStateMachine : IStateMachine<MachineState, Trigger>
{
protected StateMachine<MachineState, Trigger> Machine;
public MachineState CurrentState { get; set; }
public void Fire(Trigger trigger)
{
Machine.Fire(trigger);
}
public async Task FireAsync(Trigger trigger)
{
await Machine.FireAsync(trigger);
}
public bool IsInState(MachineState state)
{
return Machine.IsInState(state);
}
public void Register(MachineState state, Action callback)
{
Machine.Configure(state)
.OnEntry(() => callback.Invoke());
}
public void RegisterAsync(MachineState state, Func<Task> callback)
{
Machine.Configure(state)
.OnEntryAsync(async () => await callback.Invoke());
}
public void Start()
{
ConfigureMachine();
Machine.Activate();
}
protected void ConfigureMachine()
{
Machine = new StateMachine<MachineState, Trigger>(MachineState.Off);
Machine.Configure(MachineState.Off)
.Permit(Trigger.TurnOn, MachineState.On);
Machine.Configure(MachineState.On)
.Permit(Trigger.TurnOff, MachineState.Off);
}
}
public interface IStateMachine<TState, TTrigger>
{
TState CurrentState { get; set; }
bool IsInState(TState state);
void Fire(TTrigger trigger);
Task FireAsync(TTrigger trigger);
void Start();
void Register(TState state, Action callback);
void RegisterAsync(TState state, Func<Task> callback);
}
public enum MachineState
{
Off,
On
}
public enum Trigger
{
TurnOff,
TurnOn
}
我試圖找到使用 Autofac 進行此類注入的示例,但我找不到其他遇到過類似問題的人。
容器將直接解析ConcreteStateMachine
的實例。
正如在container.Resolve<IStateMachine<MachineState, Trigger>>()
中正確提供了一個ConcreteStateMachine
,但 Autofac 似乎不知道如何將實例發送到Consumer
。
ConcreteStateMachine
的Machine
字段未初始化,為null
。 所以它在NullReferenceException
中失敗:
public void Register(MachineState state, Action callback)
{
Machine.Configure(state)
.OnEntry(() => callback.Invoke());
}
只是在創建人為示例時引入錯誤的情況......
我從未在 Consumer 的構造函數中調用 Machine.Start(),它在調用 Register 之前實例化內部 StateMachine,Register 調用底層 StateMachine 上的方法。 這導致在創建 Consumer 時拋出異常,實際上並不是 Autofac 配置問題。
對不起!
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.