C# StructureMap中的循环依赖关系-可以通过属性注入来打破它们吗?
我在structuremap中得到了最简单的循环依赖关系——类A在其构造函数中依赖于类B,类B在其构造函数中依赖于类A。为了打破依赖关系,我让类B将类A作为属性,而不是构造函数参数,但structuremap仍然会抱怨 我见过在其他DI框架中使用此方法破坏循环依赖关系-这是Structuremap的问题还是我做错了什么 编辑: 我应该提到,B类的属性是一个A类实例数组,如下所示:C# StructureMap中的循环依赖关系-可以通过属性注入来打破它们吗?,c#,dependency-injection,structuremap,circular-dependency,C#,Dependency Injection,Structuremap,Circular Dependency,我在structuremap中得到了最简单的循环依赖关系——类A在其构造函数中依赖于类B,类B在其构造函数中依赖于类A。为了打破依赖关系,我让类B将类A作为属性,而不是构造函数参数,但structuremap仍然会抱怨 我见过在其他DI框架中使用此方法破坏循环依赖关系-这是Structuremap的问题还是我做错了什么 编辑: 我应该提到,B类的属性是一个A类实例数组,如下所示: x.For<IB>().Singleton().Use<B>().Setter(y =>
x.For<IB>().Singleton().Use<B>().Setter(y => y.ArrayOfA).IsTheDefault();
x.For<IB>().Use<B>()
.OnCreation((ctx, instance) =>
{
instance.ArrayOfA = new IA[] {new A(instance) };
});
x.For().Singleton().Use().Setter(y=>y.ArrayOfA).IsTheDefault();
为了澄清,我希望发生以下事件:
- 构造B的一个实例,“B”
- 构造一个“A”的实例,将“b”注入其构造函数
- 将“b.ArrayOfA”设置为[“a”]
interface ILoader { }
interface ILoaderManager { }
class Loader : ILoader
{
public Loader(ILoaderManager lm) { }
}
class LoaderManager : ILoaderManager
{
public ILoader Loader { get; set; } // Was an array, but same circular dependency appears here
}
ObjectFactory.Configure
(
x =>
{
x.For<ILoader>.Singleton().Use<Loader>();
x.For<ILoaderManager>().Singleton().Use<LoaderManager>().OnCreation((c, a) => a.Loader = c.GetInstance<ILoader>());
}
);
接口ILoader{}
接口ILoaderManager{}
类装入器:ILoader
{
公共加载程序(ILoaderManager lm){}
}
类装入器管理器:ILoaderManager
{
公共ILoader加载程序{get;set;}//是一个数组,但此处显示相同的循环依赖项
}
ObjectFactory.Configure
(
x=>
{
x、 For.Singleton().Use();
x、 For().Singleton().Use().OnCreation((c,a)=>a.Loader=c.GetInstance());
}
);
验证配置会导致“使用RequestedType:IocTest2.ILoader检测到双向依赖性问题…”StructureMap可能会在其将在其解析的对象上填充公共可设置属性的位置执行此操作。根据文件, 默认情况下,所有公共“setter”都是可选的,这意味着只有在为特定实例显式配置这些setter时,才会设置它们 那么,您是否碰巧将属性设置为自动连接?如果是这样,您仍然会遇到循环依赖性问题
编辑:我知道你有。在您的实例中,由于B注入了[],StructureMap必须解析每个A对需要[]的B的依赖关系,依此类推…您可以得到的最接近的结果如下:
x.For<IB>().Singleton().Use<B>().Setter(y => y.ArrayOfA).IsTheDefault();
x.For<IB>().Use<B>()
.OnCreation((ctx, instance) =>
{
instance.ArrayOfA = new IA[] {new A(instance) };
});
x.For().Use()
.OnCreation((ctx,实例)=>
{
instance.ArrayOfA=newia[]{newa(实例)};
});
如果
A
有其他依赖项需要从容器中解析,则可以从OnCreation lambda中的ctx
中检索它们。StructureMap还可以通过使用延迟解析的解决方法处理双向情况
如果您有一个简单的情况,如依赖于ClassB
的ClassA
和依赖于ClassA
的ClassB
,那么您可以选择其中一个并将依赖项转换为惰性依赖项。这种方法对我有效,而那个错误再也没有出现过
public class ClassA
{
private readonly Lazy<IClassB> _classB;
public ClassA(Lazy<IClassB> classB)
{
_classB = classB;
}
public IClassB ClassB => _classB.Value;
}
public class ClassB
{
public IClassA _classA { get; set; }
public ClassB (IClassA classA)
{
_classA = classA;
}
}
公共类ClassA
{
私有只读懒_classB;
公共类A(惰性类B)
{
_classB=classB;
}
公共IClassB ClassB=>\u ClassB.Value;
}
公共B类
{
公共IClassA _classA{get;set;}
公共B类(IClassA classA)
{
_classA=classA;
}
}
这里有更多信息:IIRC,我在温莎城堡也做过同样的尝试。它在解析组件的构造函数后进行属性解析,这意味着循环依赖关系实际上被打破了。假设我不是在幻想这个事实,我想知道StructureMap是否有类似的功能?这里有一个Windsor和StructureMap的循环依赖解决方案示例:。我知道它有点老,但仍然适用。我注意到它使用了
名为(“Processor 1”)
的装置作为最后一个SetterDependence的配置,也许这会有所帮助?您好statenjason,非常感谢您的帮助和链接。我尝试了一下,仍然得到了循环依赖。我已经用一个小的代码片段修改了我的问题来说明这个问题。嗨,Joshua-我刚刚尝试了一下,得到了一个“双向依赖问题”-我认为这是StructureMap中循环依赖的一个标志?通过StructureMap构建和设置对象是否有效地实现了原子化,因此无法解析循环引用?这似乎不太可能,但到目前为止我还不能让它工作……双向依赖性问题确实表明存在循环引用。但是,我提供的代码示例将起作用,因为B的实例是在调用OnCreation lambda之前创建的。然后,您可以将B的实例传递到A的构造函数中,然后将B的属性设置为A。我已经测试了上面的代码,它可以正常工作。如果您仍然遇到循环引用问题,那么肯定还有其他您没有提到的依赖项。我应该澄清,在使用我的代码示例时,您不应该将任何策略设置为让StructureMap在B上执行setter注入。您正在OnCreation lambda中手动执行setter注入。