8

Tôi có loại phụ thuộc vòng tròn đơn giản nhất trong structuremap - lớp A dựa vào lớp B trong hàm tạo của nó và lớp B dựa vào lớp A trong hàm tạo của nó. Để phá vỡ sự phụ thuộc, tôi đã tạo lớp B làm lớp A là một thuộc tính, chứ không phải là một đối số hàm tạo, nhưng structuremap vẫn than phiền.Các phụ thuộc thông tư trong StructureMap - chúng có thể bị phá vỡ với việc phun thuộc tính không?

Tôi đã thấy các phụ thuộc vòng tròn bị hỏng bằng phương pháp này trong các khung công tác DI khác - đây có phải là vấn đề với Structuremap hoặc tôi đang làm điều gì sai?

Edit: tôi nên đề cập đến tài sản đó lớp B là một mảng các trường lớp A, dây lên như thế này:

x.For<IB>().Singleton().Use<B>().Setter(y => y.ArrayOfA).IsTheDefault(); 

Chỉ cần làm rõ, tôi muốn các chuỗi sự kiện sau xảy ra:

  • Xây dựng một thể hiện của b, "b"
  • Xây dựng một thể hiện của A, "a", tiêm "b" vào constructor của nó
  • Set "b.ArrayOfA" tới [ "a"]

Và tôi muốn tất cả điều này xảy ra sử dụng autowiring, nếu có thể ...

Sửa 2: Dưới đây là một ví dụ đơn giản mà sử dụng dây rõ ràng lên:

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>()); 
    } 
); 

Members những nguyên nhân cấu hình "hai chiều phụ thuộc vấn đề phát hiện với RequestedType: IocTest2.ILoader ..."

Trả lời

3

Gần nhất bạn có thể nhận được là một cái gì đó như thế này:

x.For<IB>().Use<B>() 
    .OnCreation((ctx, instance) => 
    { 
     instance.ArrayOfA = new IA[] {new A(instance) }; 
    }); 

Nếu A có các phụ thuộc khác mà bạn muốn giải quyết từ vùng chứa, bạn có thể truy xuất chúng từ ctx trong lambda OnCreation.

+0

Xin chào Joshua - Tôi vừa cho nó đi và nhận được một "Vấn đề phụ thuộc hai chiều" - Tôi nghĩ đây là dấu hiệu của sự phụ thuộc vòng tròn trong StructureMap? Việc xây dựng và thiết lập một đối tượng bằng StructureMap có hiệu quả nguyên tử hay không, vì vậy các tham chiếu vòng tròn không thể được giải quyết? Có vẻ như không, nhưng tôi đã không thể làm cho nó hoạt động cho đến nay ... – Andy

+0

Sự phụ thuộc hai chiều Vấn đề chỉ ra một tham chiếu vòng tròn. Tuy nhiên, mẫu mã mà tôi cung cấp S W làm việc, như thể hiện của B được tạo trước khi lambda OnCreation được gọi. Sau đó bạn có thể chuyển thể hiện B đó vào hàm tạo của A, và sau đó thiết lập thuộc tính B thành A. Tôi đã thử nghiệm mã ở trên và nó hoạt động. Nếu bạn vẫn nhận được các vấn đề tham chiếu vòng tròn, phải có các phụ thuộc khác mà bạn chưa đề cập đến. –

+0

Tôi nên làm rõ rằng khi sử dụng ví dụ mã của tôi, bạn KHÔNG nên đặt bất kỳ chính sách nào để có StructureMap thực hiện phép đặt setter trên B. Bạn đang tự thực hiện việc tiêm setter trong lambda OnCreation. –

0

StructureMap có khả năng thực hiện Setter Injection nơi nó sẽ điền các thuộc tính có thể đặt trước công khai vào một đối tượng mà nó đang giải quyết. Theo tài liệu,

Theo mặc định, tất cả các "Setters" công cộng là không bắt buộc, có nghĩa là những setters sẽ chỉ được thiết lập nếu chúng được cấu hình một cách rõ ràng cho một Instance cụ

Vì vậy, có bạn tình cờ thiết lập các thuộc tính để được tự động có dây? Nếu vậy, bạn vẫn sẽ gặp vấn đề phụ thuộc vòng tròn.

Chỉnh sửa: Tôi thấy rằng bạn có. Trong trường hợp của bạn bởi vì B đã A [] tiêm, StructureMap phải giải quyết từng Một phụ thuộc cho một B cần A [], và vân vân ...

+0

IIRC, tôi đã cố gắng điều tương tự ở Lâu đài Windsor. Nó đã giải quyết tài sản sau khi giải quyết các nhà xây dựng của thành phần, điều đó có nghĩa là sự phụ thuộc vòng tròn đã bị phá vỡ một cách hiệu quả. Giả sử tôi đã không mơ thấy điều này, tôi đã tự hỏi nếu StructureMap có một cơ sở tương tự? – Andy

+0

Có một ví dụ về các giải pháp phụ thuộc vòng tròn với Windsor và StructureMap ở đây: http://bit.ly/aZsr9c. Tôi biết nó lớn hơn một chút nhưng vẫn có thể áp dụng. Tôi nhận thấy rằng nó đã sử dụng 'TheInstanceNamed (" Processor1 ")' cho cấu hình SetterDependency cuối cùng, có lẽ điều đó sẽ giúp ích? – statenjason

+0

Hi statenjason, cảm ơn rất nhiều vì sự giúp đỡ của bạn và liên kết. Tôi đã cho nó một đi và vẫn có phụ thuộc vòng tròn. Tôi đã sửa đổi câu hỏi của mình bằng một đoạn mã nhỏ để minh họa sự cố. – Andy

5

Cấu trúcBản đồ có thể xử lý tình huống hai chiều cũng với giải pháp thay thế bằng cách sử dụng độ phân giải Lười biếng.

Nếu bạn có một tình huống đơn giản như ClassA mà phụ thuộc vào ClassBClassB điều đó phụ thuộc của ClassA, sau đó bạn có thể chọn một trong số họ và chuyển đổi phụ thuộc như một sự phụ thuộc Lazy. Bằng cách này làm việc cho tôi và không bị lỗi mà không bao giờ xuất hiện một lần nữa ..

public class ClassA 
{ 
    private readonly Lazy<IClassB> _classB; 

    public Thing1(Lazy<IClassB> classB) 
    { 
     _classB = classB; 
    } 

    public IClassB ClassB => _classB.Value; 
} 

public class ClassB 
{ 
    public IClassA _classA { get; set; } 

    public ClassB (IClassA classA) 
    { 
     _classA = classA; 
    } 
} 

Thông tin thêm ở đây: http://structuremap.github.io/the-container/lazy-resolution/

+0

Điều này là ** nhiều ** tốt hơn câu trả lời được chấp nhận. –