2011-11-04 33 views
6

Tôi đang sử dụng ví dụ về Registry DSL để định cấu hình structuremap. Nhưng làm điều này làm cho tất cả các loại đăng ký của tôi có sẵn trong tất cả các lớp của ứng dụng của tôi, nơi tôi thêm một refernce vào bản đồ cấu trúc. Tôi không muốn lớp kinh doanh của tôi biết bất cứ điều gì về lớp truy cập dữ liệu của tôi và ngược lại. Làm thế nào để tôi có được structuremap để chỉ đăng ký các loại cụ thể cho mỗi lớp của tôi?Sơ đồ cấu trúc - Cách đăng ký một số loại nhất định trong các lớp nhất định

Đây là mã trong tập tin Global.asax của tôi:

ObjectFactory.Initialize(x => 
{ 
    x.AddRegistry<RegistryIOC>(); 
}); 

Và đây là lớp RegistryIOC tôi:

public class RegistryIOC : SMRegistry 
{ 

    public RegistryIOC() 
    { 
     For<IProfileService>.Use<ProfileService>(); 
     For<IProctorService>().Use<ProctorService>(); 

     //Business Logic Objects 
     For<IQual>().Use<Qual>(); 
     For<ITest>().Use<Test>(); 
     For<IBoldface>().Use<Boldface>(); 
     For<ITrainingPlan>().Use<TrainingPlan>(); 
     For<IUnit>().Use<Unit>(); 

     //Data Transfer Objects 
     For<IGenericDTO>().Use<GenericDTO>(); 
     For<IProfileDTO>().Use<ProfileDTO>(); 
     For<IQualDTO>().Use<QualDTO>(); 
     For<IPermissionDTO>().Use<PermissionDTO>(); 

     //Repository Objects 
     For<IProctorRepository>().Use<ProctorRepository>(); 
     For<IQualsRepository>().Use<QualsRepository>(); 
     For<ITestRepository>().Use<TestRepository>(); 
     For<IUnitRepository>().Use<UnitRepository>(); 
     For<IUserRepository>().Use<UserRepository>(); 
    } 

} 

Thanks for the help.

+0

Bạn đang nói về loại lớp nào? Quy trình khác nhau? Máy khác nhau?Nếu tất cả chúng đều chạy trong cùng một quá trình, bạn có thể làm những gì mà tầng nghiệp vụ của bạn biết * một chút * về lớp dữ liệu của bạn, cụ thể là giao diện của nó. Không rõ bạn đang cố giải quyết vấn đề gì. Điều gì là sai với lớp RegistryIOC của bạn? –

+0

Chúng tôi có một Lớp dịch vụ, BLL và DAL là tất cả các dự án riêng biệt. Mỗi dự án tham khảo StructureMap. Lớp dịch vụ biết về hai lớp kia nhưng BLL và DAL không biết về nhau. Tôi không muốn các nhà phát triển khác sử dụng Business Objects từ bên trong DAL và ngược lại tôi không muốn các nhà phát triển sử dụng các đối tượng Repository từ bên trong BLL. Lớp dịch vụ phối hợp tất cả những điều đó. Vì vậy, việc sử dụng đăng ký tất cả các loại theo cách này làm cho tất cả các đối tượng có sẵn trên tất cả các lớp (dự án) của chúng tôi. –

+0

Vâng, * không * thêm một tham chiếu đến StructureMap từ bất kỳ lớp nào khác so với Gốc Thành phần ... –

Trả lời

3

Tôi đang sử dụng sự phản chiếu để thực hiện tác vụ này (và các tác vụ khác). Hãy để tôi cho thấy cách hoạt động.

Điều đầu tiên cần làm là xác định một giao diện cho phép chúng ta xác định các lớp học thực hiện nhiệm vụ khởi tạo:

public interface IConfigurationTask 
{ 
    void Configure(); 
} 

Tiếp theo, tạo một hoặc nhiều lớp mà thực hiện giao diện này. Các lớp này sẽ được trải rộng trên tất cả các dự án của bạn, đó là một cách khác để nói rằng bạn có thể đặt chúng "nơi chúng thuộc về".

public class RepositoryInitializer : IConfigurationTask 
{ 
    public void Configure() 
    { 
     // code that does relevant initialization goes here 
    } 
} 

Phần cuối cùng của câu đố là tìm các lớp triển khai giao diện IConfigurationTask, tạo một thể hiện của chúng và thực hiện phương pháp Định cấu hình. Đây là mục đích của ConfigurationTaskRunner:

public static class ConfigurationTaskRunner 
{ 
    public static void Execute(params string[] assemblyNames) 
    { 
     var assemblies = assemblyNames.Select(Assembly.Load).Distinct().ToList(); 
     Execute(assemblies); 
    } 

    public static void Execute(IEnumerable<Assembly> assemblies) 
    { 
     var tasks = new List<IConfigurationTask>(); 
     assemblies.ForEach(a => tasks.AddRange(a.CreateInstances<IConfigurationTask>())); 

     tasks.ForEach(t => t.Configure()); 
    } 
} 

Mã đưa ra ở đây sử dụng một phần mở rộng tùy chỉnh để lặp qua tất cả các mục trong một danh sách và thực hiện một hành động cho tất cả các mục (phương pháp ForEach). Tôi cũng đang sử dụng một reflection library để thực hiện nhiệm vụ định vị và khởi tạo các cá thể một lớp (phương thức CreateInstances), nhưng bạn có thể đạt được điều tương tự bằng cách sử dụng sự phản chiếu đơn giản (như được hiển thị trong mã bên dưới).

public static IList<T> CreateInstances<T>(this Assembly assembly) 
{ 
    var query = from type in assembly.GetTypes().Where(t => typeof(T).IsAssignableFrom(t) && typeof(T) != t) 
       where type.IsClass && ! type.IsAbstract && type.GetConstructor(Type.EmptyTypes) != null 
       select (T) Activator.CreateInstance(type); 
    return query.ToList(); 
}  

Phần cuối cùng của câu đố là kích hoạt việc thực thi ConfigurationTaskRunner. Ví dụ, trong một ứng dụng web này sẽ đi vào Application_Start trong Global.asax:

// pass in the names of the assemblies we want to scan, hardcoded here as an example 
ConfigurationTaskRunner.Execute("Foo.dll", "Foo.Domain.dll"); 

Tôi cũng đã tìm thấy nó hữu ích với một IPrioritizedConfigurationTask nguồn gốc (có thêm một tài sản ưu tiên) để cho phép trật tự chính xác trong những nhiệm vụ trước bạn thực hiện chúng. Điều này không được hiển thị trong mã ví dụ ở trên, nhưng khá tầm thường để thêm vào.

Hy vọng điều này sẽ hữu ích!

+0

Trong ví dụ này (điều này thật tuyệt vời), làm thế nào để bạn đề xuất chuỗi các phụ thuộc? Nếu tôi muốn một thể hiện của IProdRepo đã được ủng hộ bởi ProdCacheRepo được ủng hộ bởi ProdRepo ... làm thế nào bạn sẽ làm điều đó chuỗi? Hiếu kỳ! –

+0

@AndrewSiemer Tôi cho rằng đó sẽ là nhiệm vụ của khung công tác IoC (trong trường hợp này là StructureMap), dựa trên các cấu hình mà bạn cung cấp cho nó (trong các phương thức Cấu hình riêng lẻ). Mã tôi cung cấp chỉ đơn thuần là một cơ chế cho "cấu hình phân tán" của thùng chứa IoC (hoặc bất kỳ thứ gì khác bạn cần khởi tạo khi khởi động ứng dụng). –

+0

Tôi không thể sử dụng thư viện phản chiếu. Khi tôi thử mã này thông qua sự phản chiếu thông thường, a.CreateInstance ("IConfigurationTask"), tôi không nhận được kết quả gì. Có lẽ tôi đang thiếu một cái gì đó ở đâu đó ... :-( –

0

Bạn có thể tạo và định cấu hình nhiều trường hợp Container độc lập và không sử dụng tĩnh ObjectFactory ở tất cả - see this article. Sau đó, bạn sẽ có trách nhiệm cung cấp các thùng chứa thích hợp cho các lớp thích hợp.

Nhân tiện, bạn muốn xử lý giao tiếp giữa các lớp như thế nào? Nó sẽ không khó bằng cách nào đó? Tôi thà chia các cơ quan đăng ký (có thể để tách các hội đồng) và giữ nó tách riêng "thủ công" thay vì thực thi tách ở cấp cơ sở hạ tầng.

+0

Tôi không bận tâm khi thay đổi cài đặt hiện tại của mình. Nếu tốt nhất của nó để có tất cả các đăng ký tách riêng cho các lớp học trên mỗi lớp của tôi thats mát mẻ với tôi. Một phần của vấn đề của tôi là tôi không hoàn toàn hiểu làm thế nào để "cung cấp các thùng chứa thích hợp cho các lớp thích hợp." Chính xác những gì tôi đặt trong bộ nạp global.asax? –

+0

Vâng, nói chung bạn sẽ phải có các điểm nhập khác nhau cho các lớp khác nhau và mỗi lớp cần phải có (các) phương thức nhà máy riêng của mình bằng cách sử dụng vùng chứa thích hợp - theo cách này bạn sẽ có biểu đồ đối tượng riêng biệt cho mỗi lớp. Nhưng tôi không thực sự thấy làm thế nào để thực hiện bất kỳ tương tác giữa các đồ thị như vậy, vì vậy đây là lý do tại sao các câu hỏi trong đoạn thứ hai là. Cuối cùng, bạn phải có một số loại thành phần lớp trên X sử dụng thành phần cấp thấp hơn Y. Nếu X là lớp trung gian và được tạo bởi thùng chứa ở giữa, thì phụ thuộc Y của nó, ngay cả khi nó là từ lớp dưới cùng . – NOtherDev

+0

Vì vậy, nói chung câu trả lời là rất khó để có đồ thị đối tượng hoàn toàn tách rời. Đó là lý do tại sao tôi đề nghị tách ở cấp độ đăng ký/lắp ráp, thay vì cấp nhà máy đối tượng. – NOtherDev

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