Introduction:
As we know MEF is Microsoft Extensibility Framework. It helps in developing loosely coupled, extensible applications. So it leverage to plug in components in already developed application. I am not going to discuss much about the theoretical discussion rather step by step guide to how to use this framework in a sample application.
MEF works on OPEN-CLOSED Principle of the SOLID principles which is as below
Module should be closed for modification but open for extension.
MEF basic terminology:
1. Catalog : contain components those are to be plugged-in
2. Exports: These are contracts or plug-in which can be composed in the application
3. Imports: These are properties or socket where components can be plugged-in.
4. Composition: it composes all together.
Application Brief:
It is a Movie Search Windows Application and Form will have design as shown below. Initially it can search only English Comedy movies and later we will add more components to search the Adventure and Drama movies as well.
Steps:
Step 1. Create a Window Application and named it MovieSearchApplication.
Step 2. Add one label with text property as "Enter movie title" and textbox to enter Title of the movie and radio buttons to select movie categories and richtexbox to display the movie details as shown below. Add one button and enter text property as Search.
Step 3. Add one Class Library project and named it MovieDetailContract.
Step 4. Delete class1.cs file and another class file and named it as IMovie.cs and paste the below content.
Open the IMovie.cs file and add one Interface IMovie
public interface IMovie
{
IList<Movie> GetMovies(string movieTitle);
}
and a class Movie as below
public class Movie
{
public string MovieID { get; set; }
public string Title { get; set; }
public string Director { get; set; }
public DateTime ReleaseDate { get; set; }
public double Price { get; set; }
}
step 5. Compile the project and add its reference in MovieApplication Project.
step 6. Add another project class library project and named it as ComedyMovieComponent in the solution.
step 7. Add EnglishComedy.cs file and delete class1.cs file
Step 8. Add reference of MovieDetailContract assembly.
step 9. Add reference of System.Component.Composition assembly.
Step 10. Open EnglishComedy.cs file and type as below
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MovieDetailContract;
namespace ComedyMovieComponent
{
[Export(typeof(IMovie))]
[ExportMetadata("MovieCategory", "EnglishComedy")]
public class EnglishComedy : IMovie
{
private ICollection<Movie> MovieList()
{
List<Movie> movies = new List<Movie>();
Movie comedymovie = new Movie() { MovieID = "CM1001", Title = "Sister Act", Price = 450.00 };
movies.Add(comedymovie);
comedymovie = new Movie() { MovieID = "CM1011", Title = "Brazil", Price = 250.00 };
movies.Add(comedymovie);
comedymovie = new Movie() { MovieID = "CM1010", Title = "Midnight Run", Price = 150.00 };
movies.Add(comedymovie);
comedymovie = new Movie() { MovieID = "CM1101", Title = "Galaxy Quest", Price = 550.00 };
movies.Add(comedymovie);
comedymovie = new Movie() { MovieID = "CM1401", Title = "A Fish called Wanda", Price = 450.00 };
movies.Add(comedymovie);
return movies;
}
public IList<Movie> GetMovies(string movieTitle)
{
List<Movie> movies = MovieList() as List<Movie>;
var searchedmovies = movies.Where(m => m.Title.Contains(movieTitle)) ;
List<Movie> movieList = searchedmovies.ToList<Movie>();
return movieList;
}
}
}
You can see EnglishComedy class is decorated with Export attribute which help to plug the component in the MovieApplication socket while ExportMetadata attribute will help to dynamically finding the required component and using it for expected operation.
Step 11. Add a folder Components in the MovieApplication.
Step 12. Copy ComedyMovieComponent assembly in Components folder.
Step 13. Open Form1.cs file and add below code
[ImportMany]
private Lazy<IMovie, IDictionary<string, object>>[] movies { get; set; }
//This is the socket in the application where plug-in ComedyMovieComponent will fit-in.
private CompositionContainer _container;
Step 14. Add below method to create the catalog of the components.
private void InitializeParts()
{
var catalog = new AggregateCatalog();
catalog.Catalogs.Add(new DirectoryCatalog(@"D:\MEF\Mobile\MovieApplication\Components"));
_container = new CompositionContainer(catalog);
this._container.ComposeParts(this);
}
reference this method in form1 constructor as below
public Form1()
{
InitializeComponent ();
InitializeParts();
}
Step 15. Now add below on click event of Search button
private void button1_Click(object sender, EventArgs e)
{
RadioButton categorybutton = groupBox1.Controls.OfType<RadioButton>().FirstOrDefault(r => r.Checked);
string movieCategory = categorybutton.Text.Trim().Replace(" ", "").ToUpper();
string title = textBox1.Text.Trim();
bool isMovieFound = false;
foreach (Lazy<IMovie, IDictionary<string, object>> movie in movies)
{
string componentMovieCategory = movie.Metadata["MovieCategory"].ToString().ToUpper();
if (componentMovieCategory == movieCategory)
{
List<Movie> searchedMovies = movie.Value.GetMovies(title).ToList();
StringBuilder movieString = new StringBuilder();
if (searchedMovies != null && searchedMovies.Count > 0)
{
isMovieFound = true;
foreach (var searchedMovie in searchedMovies)
{
movieString.AppendFormat("MovieID: {0}", searchedMovie.MovieID);
movieString.AppendFormat("{1}Movie Title: {0}{1} Movie Price: {2}", searchedMovie.Title, Environment.NewLine, searchedMovie.Price);
movieString.AppendFormat("{0}====================================={0}",Environment.NewLine);
}
}
richTextBox1.Text = movieString.ToString();
}
}
if (!isMovieFound)
{
MessageBox.Show("Movie / Category is not available");
}
}
Now run the application
1. Enter movie title as Braz
2. Select English Comedy radio button
3. Click on the search button
output will come like belowAs
Now select English Adventure category and click on the Search button
Selected Movie/Category is not available message will prompt you.
English Adventure Component Development:
Now we will create English Adventure movies component and will add this to components directory of UI and this will start working.
Step 1. Add another class Library EnglishAdventureComponent in the solution
Step 2. Delete class1.cs and add EnglishAdventure class.
Step 3. Add reference of MovieDetailContract assembly.
Step 3. Add reference of MovieDetailContract assembly.
Step 4. Add reference of System.Component.Composition assembly.
Step 5. Open the EnglishAdventure class file and add below code
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MovieDetailContract;
namespace EnglishAdventureComponent
{
[Export(typeof(IMovie))]
[ExportMetadata("MovieCategory", "EnglishAdventure")]
public class EnglishAdventure:IMovie
{
private ICollection<Movie> MovieList()
{
List<Movie> movies = new List<Movie>();
Movie comedymovie = new Movie() { MovieID = "CM1001", Title = "SpiderMan 2", Price = 450.00 };
movies.Add(comedymovie);
comedymovie = new Movie() { MovieID = "CM1011", Title = "SpiderMan", Price = 250.00 };
movies.Add(comedymovie);
comedymovie = new Movie() { MovieID = "CM1010", Title = "XMan", Price = 150.00 };
movies.Add(comedymovie);
comedymovie = new Movie() { MovieID = "CM1101", Title = "Avatar", Price = 550.00 };
movies.Add(comedymovie);
comedymovie = new Movie() { MovieID = "CM1401", Title = "Star Wars 1", Price = 450.00 };
movies.Add(comedymovie);
return movies;
}
public IList<Movie> GetMovies(string movieTitle)
{
List<Movie> movies = MovieList() as List<Movie>;
var searchedmovies = movies.Where(m => m.Title.Contains(movieTitle));
List<Movie> movieList = searchedmovies.ToList<Movie>();
return movieList;
}
}
}
Step 5. Open the EnglishAdventure class file and add below code
using System;
using System.Collections.Generic;
using System.ComponentModel.Composition;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using MovieDetailContract;
namespace EnglishAdventureComponent
{
[Export(typeof(IMovie))]
[ExportMetadata("MovieCategory", "EnglishAdventure")]
public class EnglishAdventure:IMovie
{
private ICollection<Movie> MovieList()
{
List<Movie> movies = new List<Movie>();
Movie comedymovie = new Movie() { MovieID = "CM1001", Title = "SpiderMan 2", Price = 450.00 };
movies.Add(comedymovie);
comedymovie = new Movie() { MovieID = "CM1011", Title = "SpiderMan", Price = 250.00 };
movies.Add(comedymovie);
comedymovie = new Movie() { MovieID = "CM1010", Title = "XMan", Price = 150.00 };
movies.Add(comedymovie);
comedymovie = new Movie() { MovieID = "CM1101", Title = "Avatar", Price = 550.00 };
movies.Add(comedymovie);
comedymovie = new Movie() { MovieID = "CM1401", Title = "Star Wars 1", Price = 450.00 };
movies.Add(comedymovie);
return movies;
}
public IList<Movie> GetMovies(string movieTitle)
{
List<Movie> movies = MovieList() as List<Movie>;
var searchedmovies = movies.Where(m => m.Title.Contains(movieTitle));
List<Movie> movieList = searchedmovies.ToList<Movie>();
return movieList;
}
}
}
No comments:
Post a Comment