我有一些业务对象必须一起使用才能获得特定的结果。请查看以下非常简单的示例以供参考。
我的问题是:如何在Station类中使用DI获取对代理的引用?我最喜欢构造函数注入,但是这不可能,Station类已经将stationCode作为必需项。
有什么想法吗?
用法:的
var station1 = new Station("xx");
var station2 = new Station("yy");
var route = new Route(station1, station2);
var length = route.GetLength();
public class Location
{
public int Position {get; set;}
}
public interface IAgent
{
Location GetLocation(string stationCode);
}
public class Station
{
private string _stationCode;
public Station(string stationCode)
{
_stationCode = stationCode;
}
public Location GetLocation()
{
// issue here: how to get a reference to the agent instance using DI
_agent.GetLocation(_stationCode);
}
}
public class Route
{
private Station _station1;
private Station _station2;
public Route(Station station1, Station station2)
{
_station1 = station1;
_station2 = station2;
}
public int GetLength()
{
var location1 = _station1.GetLocation();
var location2 = _station2.GetLocation();
result = location2.Position - location1.Position;
return result;
}
}
答案 0 :(得分:1)
您的课程似乎遇到了身份危机。使用DI时,您应该只有两种类型来处理 - injectables and newables。你的Station
类似乎是一个kludge,因为它既提供服务(有依赖关系)又有状态。为了使您的类对DI友好,您应该设计仅为仅对状态(服务)执行某些操作的类提供状态的类。
此类是可注入的 - 也就是说,它应该从DI容器连接。
public interface IRoute
{
int GetLength(Station station1, Station station2);
}
public class Route : IRoute
{
private readonly IAgent _agent;
public Route(IAgent agent)
{
if (agent == null) throw new ArgumentNullException("agent");
_agent = agent;
}
public int GetLength(Station station1, Station station2)
{
var location1 = _agent.GetLocation(station1.StationCode);
var location2 = _agent.GetLocation(station2.StationCode);
result = location2.Position - location1.Position;
return result;
}
}
这个类是新的 - 也就是说,你应该总是使用new关键字来实例化它。
public class Station
{
private string _stationCode;
public Station(string stationCode)
{
_stationCode = stationCode;
}
public string StationCode
{
get { return _stationCode; }
// Optional: provide setter here
}
}
var station1 = new Station("xx");
var station2 = new Station("yy");
// IRoute is injected where you need to make the calculation
var length = _route.GetLength(station1, station2);
将Route
重命名为更合适的东西可能会更好,因为它不提供路线,而是计算路线长度。
坦率地说,如果你的
Station
类没有任何其他状态而不是单个字符串变量,那么消除该类可能更有意义,只需使用station1
和{{1}的字符串}}。但这主要是个人品味。
答案 1 :(得分:0)
两种类型的处理概念,注射剂和新药,是一个好主意。但是当newables应该只包含有限的业务逻辑时,你就会偏离纯粹的面向对象的概念。为复杂域模型编写代码时,新的业务类包含业务逻辑和数据。我认为这也是问题的意图。 Station和Route类是简单的例子,实际上包含更多的逻辑和数据。
因此,我建议通过将存储代码与业务逻辑分开来更好地分离关注点。我看到了两种常见的解决方案。
当数据加载到内存中时,单独的 StationStore 类是一个可注入的加载站,并将它们存储在业务域的上下文中,例如。在静态属性中:
public IEnumarable<Station> Station.Store { get; internal set; }
所有DI代码都可以隐藏在业务基类中。将DI依赖项放在那里不那么令人不安。因此,可以根据提供的模板类型在通用基类中解析代理。
public class Station : BusinessClass<Station, StationAgent>
{
public string StationCode { get; internal set; }
public Location Location { get; internal set; }
public Station(string stationCode)
{
base.Load(stationCode, this);
}
}