当中间有抽象 class 时,将 Unity code-as-config 移动到 XML
Move Unity code-as-config to XML when having abstract class in between
我有一个通过代码配置的工作 Unity 容器。我必须移动到 xml 配置,但无法正确设置。我不知道我错过了什么 - 也许有人知道解决方案并可以帮助我!
我的解决方案是正确地对我的 FIX 协议库进行分层,以不同方式处理不同供应商特定的消息,但要为此提供强大的支持 API。
我有两个接口:
public interface ICriteria
{
bool AreMet(Message message);
}
public interface IConsumer
{
ICriteria Criteria { get; }
void HandleMessage(Message message);
}
消费者有一个默认的抽象实现:
namespace Fix.MessageHandling
{
public abstract class Consumer : IConsumer
{
private readonly ICriteria criteria;
protected readonly IProcessor Processor;
public ICriteria Criteria
{
get { return this.criteria; }
}
protected Consumer(IProcessor processor, ICriteria criteria)
{
//...
}
}
}
然后我得到了一些针对不同 FIX 消息类型的抽象实现:每个 Consumer 抽象都有自己的 Criteria 抽象。 (也在构造函数中引用)例如
namespace Fix.MessageHandling.ExecutionReport
{
public abstract class Consumer : MessageHandling.Consumer
{
protected Consumer(IProcessor processor, Criteria criteria)
: base(processor, criteria)
{
// ...
}
}
public abstract class Criteria : ICriteria
{
// ...
}
}
我从代码中注册了 ICriteria 实例:
container.RegisterType<ICriteria, Vendor.Criteria.Spot>("SpotCriteria");
container.RegisterType<ICriteria, Vendor.Criteria.Swap>("SwapCriteria");
// etc.
之后我注册了 IConsumer 实例,在本例中是 ExecutionReportConsumer 实例,但我映射到 IConsumer:
container.RegisterType<
IConsumer,
Vendor.Consumer.Spot>("SpotConsumer",
new InjectionConstructor(
container.Resolve<IProcessor>(),
container.Resolve<ICriteria>("SpotCriteria")));
// etc.
当我解析 IConsumer-s 时,我可以从 UnityContainer 中获取所有已注册的消费者:
container.ResolveAll<IConsumer>();
这就是我在定义所有别名后尝试使用 xml 执行此操作的方式:
<register type="ICriteria" mapTo="ForwardCriteria" name="ForwardCriteria" />
<register type="IConsumer" mapTo="ForwardConsumer" name="ForwardConsumer">
<constructor>
<param name="processor" dependencyType="IProcessor" />
<param name="criteria" dependencyType="ExecutionReportCriteria" dependencyName="ForwardCriteria" />
</constructor>
</register>
如果我使用 xml 配置并为 IConsumers 调用 ResolveAll,则会出现异常
解析依赖失败,类型="Fix.MessageHandling.IConsumer",名称="ForwardConsumer"。
异常发生在:解析时。
异常是:InvalidOperationException - 类型标准没有可访问的构造函数。
发生异常时,容器是:
解析Fix.Vendor.Consumer.Forward,ForwardConsumer(映射自Fix.MessageHandling.IConsumer,ForwardConsumer)
解析构造函数 Fix.Vendor.Consumer.Forward 的参数 "criteria"(Fix.MessageHandling.IProcessor 处理器,Fix.MessageHandling.ExecutionReport.Criteria 标准)
解析 Fix.MessageHandling.ExecutionReport.Criteria,ForwardCriteria
好的,实际上这是我自己想出来的,我是一个新手,不知道该怎么做 - 所以我回答我自己的问题:]
如果我将标准接口和我的具体标准实现注册到正确的抽象基础 class,那么它就像一个魅力!
<register type="ICriteria" />
<register type="ExecutionReportCriteria" mapTo="ForwardCriteria" name="ForwardCriteria" />
<register type="IConsumer" mapTo="ForwardConsumer" name="ForwardConsumer">
<constructor>
<param name="processor" dependencyType="IProcessor" />
<param name="criteria" dependencyName="ForwardCriteria" />
</constructor>
</register>
我就是这样成功的:
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<typeAliases>
<typeAlias alias="ICriteria"
type="Fix.MessageHandling.ICriteria, MoveUnityCode-as-configToXML" />
<typeAlias alias="ExecutionReportCriteria"
type="Fix.MessageHandling.ExecutionReport.Criteria, MoveUnityCode-as-configToXML" />
<typeAlias alias="ForwardCriteria"
type="Fix.MessageHandling.ExecutionReport.ForwardCriteria, MoveUnityCode-as-configToXML" />
<typeAlias alias="IConsumer"
type="Fix.MessageHandling.IConsumer, MoveUnityCode-as-configToXML" />
<typeAlias alias="ForwardConsumer"
type="Fix.MessageHandling.ExecutionReport.ForwardConsumer, MoveUnityCode-as-configToXML" />
<typeAlias alias="IProcessor"
type="Fix.MessageHandling.IProcessor, MoveUnityCode-as-configToXML" />
<typeAlias alias="Processor"
type="Fix.MessageHandling.Processor, MoveUnityCode-as-configToXML" />
</typeAliases>
<container>
<register type="ExecutionReportCriteria" mapTo="ForwardCriteria" name="ForwardCriteria" />
<register type="IProcessor" mapTo="Processor" />
<register type="IConsumer" mapTo="ForwardConsumer" name="ForwardConsumer">
<constructor>
<param name="processor" dependencyType="IProcessor" />
<param name="criteria" dependencyType="ExecutionReportCriteria" dependencyName="ForwardCriteria" />
</constructor>
</register>
</container>
</unity>
我有一个通过代码配置的工作 Unity 容器。我必须移动到 xml 配置,但无法正确设置。我不知道我错过了什么 - 也许有人知道解决方案并可以帮助我!
我的解决方案是正确地对我的 FIX 协议库进行分层,以不同方式处理不同供应商特定的消息,但要为此提供强大的支持 API。 我有两个接口:
public interface ICriteria
{
bool AreMet(Message message);
}
public interface IConsumer
{
ICriteria Criteria { get; }
void HandleMessage(Message message);
}
消费者有一个默认的抽象实现:
namespace Fix.MessageHandling
{
public abstract class Consumer : IConsumer
{
private readonly ICriteria criteria;
protected readonly IProcessor Processor;
public ICriteria Criteria
{
get { return this.criteria; }
}
protected Consumer(IProcessor processor, ICriteria criteria)
{
//...
}
}
}
然后我得到了一些针对不同 FIX 消息类型的抽象实现:每个 Consumer 抽象都有自己的 Criteria 抽象。 (也在构造函数中引用)例如
namespace Fix.MessageHandling.ExecutionReport
{
public abstract class Consumer : MessageHandling.Consumer
{
protected Consumer(IProcessor processor, Criteria criteria)
: base(processor, criteria)
{
// ...
}
}
public abstract class Criteria : ICriteria
{
// ...
}
}
我从代码中注册了 ICriteria 实例:
container.RegisterType<ICriteria, Vendor.Criteria.Spot>("SpotCriteria");
container.RegisterType<ICriteria, Vendor.Criteria.Swap>("SwapCriteria");
// etc.
之后我注册了 IConsumer 实例,在本例中是 ExecutionReportConsumer 实例,但我映射到 IConsumer:
container.RegisterType<
IConsumer,
Vendor.Consumer.Spot>("SpotConsumer",
new InjectionConstructor(
container.Resolve<IProcessor>(),
container.Resolve<ICriteria>("SpotCriteria")));
// etc.
当我解析 IConsumer-s 时,我可以从 UnityContainer 中获取所有已注册的消费者:
container.ResolveAll<IConsumer>();
这就是我在定义所有别名后尝试使用 xml 执行此操作的方式:
<register type="ICriteria" mapTo="ForwardCriteria" name="ForwardCriteria" />
<register type="IConsumer" mapTo="ForwardConsumer" name="ForwardConsumer">
<constructor>
<param name="processor" dependencyType="IProcessor" />
<param name="criteria" dependencyType="ExecutionReportCriteria" dependencyName="ForwardCriteria" />
</constructor>
</register>
如果我使用 xml 配置并为 IConsumers 调用 ResolveAll,则会出现异常
解析依赖失败,类型="Fix.MessageHandling.IConsumer",名称="ForwardConsumer"。 异常发生在:解析时。
异常是:InvalidOperationException - 类型标准没有可访问的构造函数。
发生异常时,容器是:
解析Fix.Vendor.Consumer.Forward,ForwardConsumer(映射自Fix.MessageHandling.IConsumer,ForwardConsumer) 解析构造函数 Fix.Vendor.Consumer.Forward 的参数 "criteria"(Fix.MessageHandling.IProcessor 处理器,Fix.MessageHandling.ExecutionReport.Criteria 标准) 解析 Fix.MessageHandling.ExecutionReport.Criteria,ForwardCriteria
好的,实际上这是我自己想出来的,我是一个新手,不知道该怎么做 - 所以我回答我自己的问题:]
如果我将标准接口和我的具体标准实现注册到正确的抽象基础 class,那么它就像一个魅力!
<register type="ICriteria" />
<register type="ExecutionReportCriteria" mapTo="ForwardCriteria" name="ForwardCriteria" />
<register type="IConsumer" mapTo="ForwardConsumer" name="ForwardConsumer">
<constructor>
<param name="processor" dependencyType="IProcessor" />
<param name="criteria" dependencyName="ForwardCriteria" />
</constructor>
</register>
我就是这样成功的:
<unity xmlns="http://schemas.microsoft.com/practices/2010/unity">
<typeAliases>
<typeAlias alias="ICriteria"
type="Fix.MessageHandling.ICriteria, MoveUnityCode-as-configToXML" />
<typeAlias alias="ExecutionReportCriteria"
type="Fix.MessageHandling.ExecutionReport.Criteria, MoveUnityCode-as-configToXML" />
<typeAlias alias="ForwardCriteria"
type="Fix.MessageHandling.ExecutionReport.ForwardCriteria, MoveUnityCode-as-configToXML" />
<typeAlias alias="IConsumer"
type="Fix.MessageHandling.IConsumer, MoveUnityCode-as-configToXML" />
<typeAlias alias="ForwardConsumer"
type="Fix.MessageHandling.ExecutionReport.ForwardConsumer, MoveUnityCode-as-configToXML" />
<typeAlias alias="IProcessor"
type="Fix.MessageHandling.IProcessor, MoveUnityCode-as-configToXML" />
<typeAlias alias="Processor"
type="Fix.MessageHandling.Processor, MoveUnityCode-as-configToXML" />
</typeAliases>
<container>
<register type="ExecutionReportCriteria" mapTo="ForwardCriteria" name="ForwardCriteria" />
<register type="IProcessor" mapTo="Processor" />
<register type="IConsumer" mapTo="ForwardConsumer" name="ForwardConsumer">
<constructor>
<param name="processor" dependencyType="IProcessor" />
<param name="criteria" dependencyType="ExecutionReportCriteria" dependencyName="ForwardCriteria" />
</constructor>
</register>
</container>
</unity>