2009-05-22 19 views
6

Giả sử tôi có giao diện IRepository và SqlRepository thực thi của nó lấy làm đối số LINQ to SQL DataContext. Giả sử rằng tôi có giao diện IService và các dịch vụ triển khai thực hiện các dịch vụ của nó gồm ba IRepository, IRepository và IRepository. Mã trình diễn bên dưới:Tiêm cùng một thể hiện DataContext trên một số kiểu với Unity

public interface IRepository<T> { } 

public class SqlRepository<T> : IRepository<T> 
{ 
    public SqlRepository(DataContext dc) { ... } 
} 

public interface IService<T> { } 

public class Service<T,T1,T2,T3> : IService<T> 
{ 
    public Service(IRepository<T1> r1, IRepository<T2>, IRepository<T3>) { ... } 
} 

Có cách nào trong khi tạo Lớp dịch vụ để tiêm cả ba kho với cùng một DataContext không?

+0

cập nhật câu trả lời của tôi –

Trả lời

7

Tất cả bạn cần làm là đảm bảo khi bạn đăng ký Datacontext với container Unity của bạn sử dụng PerResolveLifetimeManager hoặc trong config:

<type type="<namespace>.DataContext, <assembly>"> 
    <lifetime type="Microsoft.Practices.Unity.PerResolveLifetimeManager, Microsoft.Practices.Unity" /> 
</type> 

hoặc trong mã:

container.RegisterType<DataContext>(new PerResolveLifetimeManager()); 

sau đó bất cứ khi nào container giải quyết Service bất kỳ phụ thuộc nào cũng yêu cầu DataContext sẽ được cung cấp chính xác như nhau. Nhưng yêu cầu tiếp theo để giải quyết Service sẽ tạo một DataContext mới.

0

Nếu tôi hiểu câu hỏi của bạn một cách chính xác (và nếu bạn đang sử dụng thống nhất ... Tôi cho rằng bạn làm vì bạn đã taggged nó với sự đoàn kết), bạn có thể làm một cái gì đó như thế này:

Trong implementions kho của bạn,

[InjectionConstructor] 
public SqlRepository(
    [Dependency] DataContext ctx) 

nhưng sau đó bạn phải đánh dấu trình thu dịch vụ theo cách tương tự và sử dụng vùng chứa để giải quyết các dịch vụ của bạn cũng như kho lưu trữ. DataContext cũng phải nằm trong vùng chứa để làm cho nó hoạt động.

Một phương pháp khác là để làm một cái gì đó như thế này với kho lưu trữ của bạn:

[InjectionMethod] 
public void Initialize(
    [Dependency] DataContext ctx 

này sẽ cho thống nhất để gọi phương pháp này nếu bạn sẽ, trong constructor dịch vụ của bạn, sử dụng thống nhất với phương pháp tích tụ ... một cái gì đó như thế này:

unitycontainer.BuildUp<IRepository>(repository); 

tôi đoán đó là không khá gì bạn đang tìm kiếm nhưng xin vui lòng cho tôi biết nếu tôi đang đi đúng hướng và tôi sẽ xem nếu tôi có thể giúp bạn thêm ...

Chúc mừng/J

+0

Cảm ơn bạn đã thử, nhưng thực sự, những gì tôi đang cố gắng hoàn thành, là sử dụng cùng một cá thể DataContext trong khi khởi tạo lớp dịch vụ. Điều này là cần thiết để hỗ trợ các giao dịch cho Repository1, Repository2 và Repository3. ContainertLifeTime không hoạt động trong trường hợp của tôi, bởi vì tôi muốn có DataContext mới cho mỗi cá thể Service mới. – Sergejus

+1

Thực ra, tôi nghĩ rằng cách tiếp cận của anh ấy tương tự như phương pháp số 2 của tôi ở trên. Anh ta đang tiêm phương thức Initialize và tạo vùng chứa ở đó, sau đó xử lý nó sau cuộc gọi. Một cái gì đó như thế này: -> precall. khởi tạo Unity Container, sử dụng ContainerControlledLifetimeManager để chúng là những người độc thân. -> Dịch vụ Khởi tạo cuộc gọi: giải quyết văn bản dữ liệu, sẽ luôn là cùng một đoạn mã dữ liệu miễn là Vùng chứa được tạo trong phần tử nằm trong phạm vi. -> Đăng cuộc gọi: Vứt bỏ hộp chứa ... –

0

Bạn đã thử sử dụng phương thức RegisterInstance() cho vùng chứa thống nhất chưa? Một cái gì đó như thế này có thể hoạt động:

tĩnh công cộng UnityContainer CreateContainer() { UnityContainer container = new UnityContainer();

 try 
     { 
      var section = ConfigurationManager.GetSection("unity") as UnityConfigurationSection; 

      if (section != null) 
      { 
       section.Containers[0].Configure(container); 
      } 
     } 
     catch (Exception ex) 
     { 
      TraceLogger.LogMessage("Configurarion Error for Unity Container", ex.Message, TraceEventType.Critical); 
      Environment.Exit(1); 
     } 


     container.RegisterInstance(new DataContext()); 
     return container; 
    } 

Bây giờ, mỗi lần thùng chứa này cố xây dựng một đối tượng cần DataContext, cùng một trường hợp sẽ được chuyển. Bạn thậm chí có thể cấu hình DataContext trước khi đăng ký thể hiện của nó.

CẬP NHẬT: Một tùy chọn (bây giờ, tôi không biết đây có thực sự là một cách hay không, nhưng điều này làm việc cho tôi) là tạo một vùng chứa khác nhau cho từng đối tượng bạn sẽ tạo. Một cái gì đó như:

UnityContainer container1 = ContainerFactory.CreateContainer(); 
UnityContainer container2 = ContainerFactory.CreateContainer(); 
UnityContainer container3 = ContainerFactory.CreateContainer(); 
MyObject1 object1 = container1.Resolve<MyObject1>(); 
MyObject2 object2 = container2.Resolve<MyObject2>(); 
MyObject3 object3 = container3.Resolve<MyObject3>(); 

hoặc một cách tóm tắt hơn:

MyObject1 object1 = ContainerFactory.CreateContainer().Resolve<MyObject1>(); 
MyObject1 object2 = ContainerFactory.CreateContainer().Resolve<MyObject2>(); 
MyObject1 object3 = ContainerFactory.CreateContainer().Resolve<MyObject3>(); 

Vâng, có rất nhiều cách để làm điều đó, tạo ra một danh sách, sử dụng mô hình nhà máy. Hy vọng nó sẽ giúp

+0

Cảm ơn đề xuất. Unfortunatelly Tôi chỉ cần bối cảnh dữ liệu giống nhau khi tạo đối tượng đơn lẻ với một số đối số DataContext. Đối với mỗi lớp Service mới, tôi cần DataContext mới. – Sergejus

3

Tôi nghĩ rằng tôi biết những gì bạn muốn làm. Tôi đang ở cùng một chiếc thuyền và đang cố gắng tìm ra một giải pháp.

Lớp dịch vụ của tôi thực hiện các thao tác trong các yêu cầu sắp tới và điều gì tùy thuộc vào nội dung. Nó chuyển nó đến một chuỗi các lớp trách nhiệm.Tôi muốn cùng một bối cảnh được chuyển đến tất cả các lớp trong vòng đời của phương thức dịch vụ được gọi là

Bạn có thể chỉ định PerResolveLifetimeManager. Cho đến nay, có vẻ như được làm việc với các trường hợp thử nghiệm của tôi:

Service Class:

public interface IServiceClass 
{ 
    void DoService(); 
} 

class ServiceClass : IServiceClass 
{ 
    private IHandler Handler { get; set; } 

    public ServiceClass(IHandler handler) 
    { 
     Handler = handler; 
    } 

    public void DoService() 
    { 
     Handler.HandleRequest(); 
    } 
} 

IHandler được thực hiện bởi hai lớp, và thực hiện Chuỗi mẫu Trách nhiệm:

public interface IHandler 
{ 
    void HandleRequest(); 
} 

class Handler : IHandler 
{ 
    private IDataContext DataContext { get; set; } 
    public Handler(IDataContext dataContext) 
    { 
     DataContext = dataContext; 
    } 

    public void HandleRequest() 
    { 
     DataContext.Save("From Handler 1"); 
    } 
} 

class Handler2 : IHandler 
{ 
    private IDataContext DataContext { get; set; } 
    private IHandler NextHandler { get; set; } 

    public Handler2(IDataContext dataContext, IHandler handler) 
    { 
     DataContext = dataContext; 
     NextHandler = handler; 
    } 

    public void HandleRequest() 
    { 
     if (NextHandler != null) 
      NextHandler.HandleRequest(); 

     DataContext.Save("From Handler 2"); 
    } 
} 

Như bạn có thể thấy, cả hai trình xử lý đều chấp nhận một thể hiện của IDataContext, mà tôi muốn giống nhau trong cả hai. Handler2 cũng chấp nhận một trường hợp của IHandler để vượt qua quyền kiểm soát (cả hai đều ở đây để chứng minh, nhưng trên thực tế, chỉ có một người sẽ xử lý yêu cầu ...)

IDataContext. Trong constructor tôi khởi tạo một Guid, và trong quá trình hoạt động, đầu ra nó vì vậy tôi có thể thấy nếu cả hai lần nó được gọi là đang sử dụng cùng một ví dụ:

public interface IDataContext 
{ 
    void Save(string fromHandler); 
} 

class DataContext : IDataContext 
{ 
    private readonly Guid _guid; 

    public DataContext() 
    { 
     _guid = Guid.NewGuid(); 
    } 

    public void Save(string fromHandler) 
    { 
     Console.Out.WriteLine("GUI: [{0}] {1}", _guid, fromHandler); 
    } 
} 

Cuối cùng, trước bạ và gọi điện thoại của dịch vụ:

private IUnityContainer container; 
    private void InitializeUnity() 
    { 
     container = new UnityContainer(); 
     container.RegisterType<IHandler, Handler2>("Handler2", 
      new InjectionConstructor(new ResolvedParameter<IDataContext>(), new ResolvedParameter<IHandler>("Handler1"))); 
     container.RegisterType<IHandler, Handler>("Handler1"); 
     container.RegisterType<IDataContext, DataContext>(new PerResolveLifetimeManager()); 
     container.RegisterType<IServiceClass, ServiceClass>("MyClass", new InjectionConstructor(new ResolvedParameter<IHandler>("Handler2"))); 
    } 

    private void CallService() 
    { 
     var service = container.Resolve<ServiceClass>("MyClass"); 
     service.DoService(); 

     // Resolving and calling again to simulate multiple resolves: 
     service = container.Resolve<ServiceClass>("MyClass"); 
     service.DoService(); 
    } 

Đây là sản phẩm tôi nhận được:

GUI: [f2250055-8a5f-4f80-a1b6-bcc5574138cf] From Handler 1 
GUI: [f2250055-8a5f-4f80-a1b6-bcc5574138cf] From Handler 2 
GUI: [22a5c0a3-3c5c-4683-807d-bf2b43f3cd0a] From Handler 1 
GUI: [22a5c0a3-3c5c-4683-807d-bf2b43f3cd0a] From Handler 2 

Hope bức tường này của văn bản trả lời câu hỏi của bạn ... Nếu không xin lỗi, nó đã truyền cảm hứng cho một giải pháp tôi cần thiết để thực hiện ...

Các vấn đề liên quan