Blog chia sẽ kinh nghiệm lập trình và Technical VN. Nơi mà các bạn có thể học tập và tham khảo về những công nghệ mới nhất hiện nay về .NET
Thứ Hai, 9 tháng 3, 2015
Hôm nay tôi sẽ giới thiệu với các bạn một Framework đến từ Microsoft - framework này không quá lớn nhưng là khá mạnh khi các bạn làm việc với Module/Plug-in trong một dự án .NET thuần túy. Hy vọng chúng ta sẽ hiểu về "Managed Extensibility Framework" hay còn gọi là MEF phần nào qua bài viết này.
I> MEF là gì
Như tôi nói ở trên, MEF được Microsoft phát triển và bổ sung vào .NET 4.0 và cao hơn vì thế chúng ta không cần phải tải thêm DLLs cũng như không phải có một cấu hình phức tạp nào để có thể sử dụng nó. MEF cho phép chúng ta làm việc theo dạng module một cách đơn giản, giảm thiểu sự ràng buộc giữa các lớp các đối tượng với nhau. Trước kia khi mà MEF chưa ra đời chúng ta thường chật vật với một dự án với quá nhiều thành phần liên kết với nhau, việc khởi tạo cũng như quản lý các thành phần này vô cùng phức tạp cho các nhà phát triển phần mềm, sau đó MS đã cho ra mắt ý tưởng là module hóa các dự án với nhiều thành phần gắn kết nhau - thứ nhất chúng ta sẽ có cái nhìn rõ ràng và sáng sủa hơn, thứ hai việc nâng cấp và mở rộng ứng dụng cũng trở nên dễ dàng hơn khi mà mã nguồn không cần phải thay đổi nhiều. Các bạn có thể hình dung qua hình ảnh sau:
Nếu các bạn để ý, MEF có phần giống với IoC, về mặt nào đó chúng giống nhau song lại không trùng lắp, MEF có một số chức năng thua xa IoC nhưng nó không bị đào thải vì nó có điểm mạnh riêng và không quá phức tạp cho việc cài đặt..png)
II> Ví dụ ứng dụng
Trước tiên chúng ta cần tạo hai project, một là "Program console" và một là "Library" như sau, trong đó ModuleA là "Library project"
Để có thể sử dụng được MEF chúng ta cần add reference cho hai project như hình trên
- "Microsoft.Practices.ServiceLocation"
- "System.ComponentModel.Composition"
Tiến hành cấu hình MEF cho "RUN.MEF project" bằng cách tạo class "MEFServiceLocator" kế thừa "ServiceLocatorImplBase", class này khi được tạo ra sẽ chịu trách nhiệm cung cấp Instance khi cần thiết.
MEFServiceLocator.cs
[code language="csharp"]
internal class MEFServiceLocator : ServiceLocatorImplBase
{
/// <summary>
/// MEF Compisition container
/// </summary>
private readonly CompositionContainer compositionContainer;
/// <summary>
/// Initializes a new instance of the <see cref="MEFServiceLocator"/> class.
/// </summary>
/// <param name="compositionContainer">The MEF composition container.</param>
public MEFServiceLocator(CompositionContainer compositionContainer)
{
this.compositionContainer = compositionContainer;
}
/// <summary>
/// Resolves the instance of the requested service.
/// </summary>
/// <param name="serviceType">Type of instance requested.</param>
/// <returns>
/// The requested service instance.
/// </returns>
protected override IEnumerable<object> DoGetAllInstances(Type serviceType)
{
var list = new List<object>();
IEnumerable<Lazy<object, object>> exports = this.compositionContainer.GetExports(serviceType, null, null);
list.AddRange(exports.Select(export => export.Value));
return list;
}
/// <summary>
/// Resolves all the instances of the requested service.
/// </summary>
/// <param name="serviceType">Type of service requested.</param><param name="key">Name of registered service you want. May be null.</param>
/// <returns>
/// Sequence of service instance objects.
/// </returns>
protected override object DoGetInstance(Type serviceType, string key)
{
List<Lazy<object, object>> exports = this.compositionContainer.GetExports(serviceType, null, key).ToList();
IOrderedEnumerable<Lazy<object, object>> orderByDescending = exports
.Where(export => ((IDictionary<string, object>) export.Metadata).ContainsKey("Priority"))
.OrderByDescending(export => ((IDictionary<string, object>) export.Metadata)["Priority"]);
if (orderByDescending.Any())
{
return orderByDescending.First().Value;
}
if (exports.Any())
{
if (exports.Count > 1)
{
return exports[0].Value;
}
return exports.Single().Value;
}
throw new ActivationException(
this.FormatActivationExceptionMessage(new CompositionException("Export not found"), serviceType, key));
}
[/code]
Quay lại "ModuleA project" chúng ta define một interface và một lớp implement cho interface này như sau
IHello.cs
[code language="csharp"]
public interface IHelloWorld
{
/// <summary>
/// Say hello
/// </summary>
void Hello();
}
[/code]
Hello.cs
[code language="csharp"]
[Export(typeof (IHelloWorld))]
public class HelloWorld : IHelloWorld
{
private int count = 0;
/// <summary>
/// Say hello
/// </summary>
public void Hello()
{
Console.WriteLine("{0} - Hello world", count);
count++;
}
}
[/code]
Chú ý rằng : các module bạn muốn MEF quản lý và làm việc thì cần phải "Export", nếu trường hợp bạn có nhiều implement cho một interface thì bạn cần export thêm key và khi getInstance cần truyền vào key đó(xem thêm ở SourceCode kèm theo)
Và bây giờ chúng ta sẽ sử dụng MEF, quay về class program.cs của "RUN.MEF", trước khi làm việc gì đó chúng ta cần Created Data cho Container, ở đây tôi làm việc đó qua hàm Create(), ở hàm này cứ mỗi module tương ứng một file Dll và tôi sẽ load file này lên và watch tất cả các Class được "Export". Tại hàm Main() tôi dùng như bình thường nhưng các bạn có để ý rằng tôi không hề new một object nào và gán cho property trước khi dùng chúng mà các property được set giá trị bằng "ServiceLocator.Current.GetInstance();" - đó là điều quan trọng và ở bất kỳ đâu trong ứng dụng, bạn chỉ cần get instance như thế là lấy đc instance mong muốn và không cần thông qua các obj khác(instance này có thể được nhiều instance khác dùng chung và updated data bằng cách này).
Program.cs
[code language="csharp"]
public class Program
{
private static CompositionContainer _compositionContainer;
private static IHelloWorld ModuleA
{
get { return ServiceLocator.Current.GetInstance<IHelloWorld>(); }
}
private static void Main(string[] args)
{
Create();
ModuleA.Hello();
ModuleA.Hello();
Console.ReadLine();
}
public static void Create()
{
var aggregateCatalog = new AggregateCatalog();
aggregateCatalog.Catalogs.Add(new DirectoryCatalog(AppDomain.CurrentDomain.BaseDirectory,
"ModuleA.Dll"));
aggregateCatalog.Catalogs.Add(new DirectoryCatalog(AppDomain.CurrentDomain.BaseDirectory,
"ModuleB.Dll"));
_compositionContainer = new CompositionContainer(aggregateCatalog);
var mefServiceLocator = new MEFServiceLocator(_compositionContainer);
ServiceLocator.SetLocatorProvider(() => mefServiceLocator);
}
}
[/code]
Còn tiếp...
Sourcecode tại đây, chúc các bạn thành công!
Phạm Tuân
Search
Popular Posts
-
Phong cách thiết kế Material Design nhắm đến những đường nét đơn giản, sử dụng nhiều mảng màu đậm nổi bật, các đối tượng đồ họa trong giao ...
-
Hôm nay chúng ta sẽ tìm hiểu cách tạo ra các menu chuột phải trên ứng dụng WPF của mình. Ở bài này chúng ta xoay quanh việc tìm hiểu cách tạ...
-
Hôm nay tôi sẽ giới thiệu với các bạn một Framework đến từ Microsoft - framework này không quá lớn nhưng là khá mạnh khi các bạn làm việc vớ...
-
WPF vượt trội hơn Winform về khoản Drawing , trong đó đặc biệt WPF hỗ trợ đồ họa rất tốt vì nó tương tác trực tiếp đến GPU. Hôm nay chúng t...
-
Để dễ hiểu, các bạn hãy hình dung rằng: cùng một tập tin thực thi *.EXE nhưng bạn DoubleClick 10 lần cách quãng vào nó thì chuyện gì sẽ sảy ...
-
ReSharper là một công cụ Add-on cho Visual Studio, nó giúp lập trình viên tốn ít thời gian cho việc xem xét định dạng code, phong cách code,...
-
Hôm nay chúng ta sẽ thử đo xem thời gian query Data của "Foreach vs LinQ vs LinQasParallel" như thế nào. Tôi tạo một tool nhỏ để l...
-
Data Binding là kĩ thuật dùng để tạo gắn kết giữa phần giao diện ( UI ) và dữ liệu thông qua phần business logic hoặc giữa các đối tượng UI...
-
Chào các bạn, hôm nay tôi sẽ giới thiệu đến mọi người về một thư viện khác giúp chúng ta xây dựng một ứng dụng WPF với giao diện mang đậm ph...
-
Đối với lập trình hiện đại hiện nay, việc hỗ trợ người dùng tối đa cũng như trừu tượng hóa các công việc đến mức gần gủi và dễ hiểu nhất cho...
Recent Posts
Blog Archive
-
▼
2015
(48)
-
▼
tháng 3
(12)
- WPF Training - Drag and Drop Trong WPF Part I
- C# - Khi Nào Nên Dùng Lớp Parallel
- WPF - Xây Dựng Ứng Dụng WPF Metro Với Thư Viện Mah...
- WPF Styles - ToggleButton Switch Phong Cách IOS
- C# - Tìm Hiểu Về MEF Trong Lập Trình C#
- C# - Kiểm Tra Tốc Độ Của Foreach vs LinQ vs LinQas...
- WPF vs Caliburn - IoC Là Gì Và Cấu Hình Bootstrapp...
- WPF vs Caliburn - Bắt Đầu HelloWorld Project Cùng ...
- WPF vs Caliburn- Tìm Hiểu Về Caliburn.Micro Framew...
- WPF vs Caliburn- Tìm Hiểu Về Caliburn.Micro Framew...
- Log4net - Configuration log4net Nâng Cao (các filt...
- WPF Training - How To Binding RadioButton Group
-
▼
tháng 3
(12)


0 nhận xét:
Đăng nhận xét