2013-05-30 5 views
14

Tôi mới dùng Unity và đang cố gắng viết một số logic Unity khởi tạo và đăng ký/giải quyết một thể hiện đơn lẻ của đối tượng Email để nó có thể được sử dụng trên nhiều đối tượng khác, một ví dụ bên dưới là OperationEntity. Vì vậy, khi nó được đăng ký nó populates các singleton email với một số giá trị từ một tập tin cấu hình, sau đó bất cứ khi nào một thể hiện của OperationEntity được tạo ra (trong trường hợp của tôi nó được deserialized) nó sử dụng cùng một singleton email. Vì vậy, tất cả logic khách hàng của tôi cần làm là deserialize OperationEntity và gọi PerformAction() - với trường hợp email được Unity xử lý.Unity Singleton Code

public interface IEmail 
{ 
    string FromName { get; set; } 
    string FromEmailAddress { get; set; } 
} 

public class Email : IEmail 
{ 
    public string FromName { get; set; } 
    public string FromEmailAddress { get; set; } 

    public Email(string fromName, string fromEmailAddress) 
    { 
     FromName = fromName; 
     FromEmailAddress = fromEmailAddress; 
    } 
} 

public class OperationEntity 
{ 
    private readonly IEmail _email; 

    public int OperationId { get; set; } 
    public string OperationName { get; set; } 
    public string ToAddress { get; set; } 

    public OperationEntity(IEmail email) 
    { 
     _email = email; 
    } 

    public void PerformAction() 
    { 
     _email.ToAddress = ToAddress; 
     _email.Body = "Some email body"; 
     _email.Deliver(); 
    } 
} 

Bất kỳ trợ giúp sẽ được đánh giá cao trong việc đang Unity này để làm việc

public static void Register(IUnityContainer container) 
    { 
     container 
      .RegisterType<IEmail, Email>(
      new InjectionFactory(c => new Email(
       "To Name", 
       "[email protected]"))); 

     var email = container.Resolve<IEmail>(); 

     container.RegisterType<OperationEntity>(
      "email", new ContainerControlledLifetimeManager(), 
      new InjectionConstructor(email)); 
    } 
+0

Tôi đã tìm kiếm một số trợ giúp với mã C# Unity cần thiết để dây này lên. – Bern

+0

Có thể [wiki về Singleton] (http://wiki.unity3d.com/index.php/Singleton) có thể có một số trợ giúp. – cregox

+0

@cregox Đó là một liên kết đến Unity3d, một thư viện đồ họa. Đây là câu hỏi về [Unity container] (https://msdn.microsoft.com/en-us/library/ff647202.aspx), một khung DI. – Andy

Trả lời

27

Trước tiên, bạn cần có một hợp lifetime manager các ContainerControlledLifetimeManager là dành cho độc thân.

Đối khởi tùy chỉnh, bạn có thể có thể sử dụng InjectionFactory

này cho phép bạn viết bất kỳ mã khởi tạo đối tượng đó.

Edit1: điều này sẽ giúp

public static void Register(IUnityContainer container) 
{ 
    container 
     .RegisterType<IEmail, Email>(
     new ContainerControlledLifetimeManager(), 
     new InjectionFactory(c => new Email(
      "To Name", 
      "[email protected]"))); 
} 

và sau đó

var opEntity = container.Resolve<OperationEntity>(); 

Edit2: Để hỗ trợ serialization, bạn sẽ phải xây dựng lại phụ thuộc sau khi bạn deserialize:

public class OperationEntity 
{ 
    // make it public and mark as dependency 
    [Dependency] 
    public IEmail _email { get; set;} 

} 

và sau đó

OperationEntity entity = somehowdeserializeit; 

// let unity rebuild your dependencies 
container.BuildUp(entity); 
+0

Tôi đã sử dụng logic từ liên kết thứ hai để giải quyết một cá thể email, nhưng làm cách nào để đảm bảo OperationEntity sẽ sử dụng cá thể đó trong hàm tạo của nó? Tôi đã thử container.RegisterType (new InjectionConstructor (email)); nhưng không may mắn. – Bern

+0

Nếu bạn sử dụng ContainerControlledLifetimeManager, thực thể singleton duy nhất sẽ luôn được tiêm vào các hàm tạo của các lớp khác. –

+0

Tôi đã bao gồm mã của tôi ở trên bằng cách sử dụng đề xuất của bạn, tiếc là tôi vẫn nhận được một giá trị null cho trường hợp email trong constructor OperationEntity vì vậy tôi đoán tôi đã bỏ lỡ một cái gì đó. Tôi có thể làm phiền bạn cho suy nghĩ của bạn. – Bern

11

Bạn có thể sử dụng:

container.RegisterType<IEmail, Email>(new ContainerControlledLifetimeManager()); 
6

Nếu IEmail là một singleton không phụ thuộc (chỉ đối số tùy chỉnh), bạn có thể mới nó lên bản thân:

container.RegisterInstance<IEmail>(new Email("To Name", "[email protected]")); 

Đó sẽ đăng ký dụ cung cấp như một singleton cho container.

Sau đó, bạn chỉ cần giải quyết các dịch vụ:

container.Resolve<OperationEntity>(); 

Và bởi vì bạn đang giải quyết một loại bê tông, không có đăng ký cần thiết. Tuy nhiên, nếu bạn muốn dịch vụ mà còn là một singleton, bạn có thể đăng ký nó sử dụng ContainerControlledLifetimeManager và sau đó tất cả các cuộc gọi đến giải quyết (hoặc khi tiêm nó như là một sự phụ thuộc vào lớp khác) sẽ trở lại cùng một ví dụ:

container.RegisterType<OperationEntity>(new ContainerControlledLifetimeManager()); 
+1

Cảm ơn vì điều này. Cuối cùng, đó là deserialization của OperationEntity đó là vấn đề chính, và tôi không chắc cách tiếp cận này giải quyết vấn đề đó. Mã cần sau khi deserializing là unityContainer.BuildUp (OperationEntity); – Bern