我一直在尋找一個答案到th是問題,我發現使用託管擴展框架很容易。在這篇文章的底部有一個更快捷的方法,但是MEF允許一個更加可擴展的方法。
MEF允許你建立從不同的組件動態訪問插件;但是它可以用來在一個單獨的程序集應用程序中快速填充集合。本質上,我們將使用它作爲將我們的程序集反映回類中的安全方式。爲了使這個功能完整,我還將實施戰略模式實體框架模型。
添加引用到您的項目,指向System.ComponentModel.Composition
。這將訪問MEF庫。
現在,我們需要實現的策略模式。如果您沒有Interfaces文件夾,請創建一個,然後添加IEntity.cs,如下所示。
IEntity。CS現在
namespace Your.Project.Interfaces
{
/// <summary>
/// Represents an entity used with Entity Framework Code First.
/// </summary>
public interface IEntity
{
/// <summary>
/// Gets or sets the identifier.
/// </summary>
/// <value>
/// The identifier.
/// </value>
int Id { get; set; }
}
}
,每次具體的實體的需要實現這個接口:
public class MyEntity : IEntity
{
#region Implementation of IEntity
/// <summary>
/// Gets or sets the identifier.
/// </summary>
/// <value>
/// The identifier.
/// </value>
public int Id { get; set; }
#endregion
// Other POCO properties...
}
我覺得這是最好的做法,而不是創建單獨的接口爲每個實體,除非你在高測試環境中工作。實際上,接口只能用於需要抽象級別的地方;主要是當一個以上的具體類將繼承,或者當使用過度熱情的Inversion of Control引擎時。如果你的生產模型中的所有東西都有接口,那麼你的架構可能會有很大的缺陷。無論如何,足夠的散漫。
現在我們已經將所有實體「策略化」了,我們可以使用MEF對它們進行整理並在您的上下文中填充集合。
在你的情況下,添加一個新的屬性:
/// <summary>
/// Gets a dynamically populated list of DbSets within the context.
/// </summary>
/// <value>
/// A dynamically populated list of DbSets within the context.
/// </value>
[ImportMany(typeof(DbSet<IEntity>))]
public IEnumerable<DbSet<IEntity>> Sets { get; private set; }
這裏的[ImportMany(typeof(DbSet<IEntity>))]
,允許MEF來填充集合。
接着,對應Export
屬性添加到每個DbSet範圍內:
[Export(typeof(DbSet<IEntity>))]
public DbSet<MyEntity> MyEntities { get; set; }
每個Import
ED和ED Export
屬性已知爲「份」。拼圖的最後一部分是組成這些部分。以下內容添加到您的上下文的構造函數:現在
// Instantiate the Sets list.
Sets = new List<DbSet<IEntity>>();
// Create a new Types catalogue, to hold the exported parts.
var catalogue = new TypeCatalog(typeof (DbSet<IEntity>));
// Create a new Composition Container, to match all the importable and imported parts.
var container = new CompositionContainer(catalogue);
// Compose the exported and imported parts for this class.
container.ComposeParts(this);
,如果運氣好的話,你應該有DbSets的動態填充的列表,你的範圍內。
我已經使用這種方法,允許通過擴展方法輕鬆截斷所有表。
/// <summary>
/// Provides extension methods for DbSet objects.
/// </summary>
public static class DbSetEx
{
/// <summary>
/// Truncates the specified set.
/// </summary>
/// <typeparam name="TEntity">The type of the entity.</typeparam>
/// <param name="set">The set.</param>
/// <returns>The truncated set.</returns>
public static DbSet<TEntity> Truncate<TEntity>(this DbSet<TEntity> set)
where TEntity : class, IEntity
{
set.ToList().ForEach(p => set.Remove(p));
return set;
}
}
我已經在上下文中添加了一個方法來截斷整個數據庫。
/// <summary>
/// Truncates the database.
/// </summary>
public void TruncateDatabase()
{
Sets.ToList().ForEach(s => s.Truncate());
SaveChanges();
}
EDIT(大修):
在溶液上方現已折舊。有些微調是必須要做的,以便現在就開始工作。要做到這一點,需要將DbSets導入到類型爲「object」的DbSet的臨時集合中,然後將此集合轉換爲所需接口類型的DbSet。基本目的,IEntity接口就足夠了。
#region Dynamic Table List
/// <summary>
/// Gets a dynamically populated list of DbSets within the context.
/// </summary>
/// <value>
/// A dynamically populated list of DbSets within the context.
/// </value>
public List<DbSet<IEntity>> Tables { get; private set; }
/// <summary>
/// Gets a dynamically populated list of DbSets within the context.
/// </summary>
/// <value>
/// A dynamically populated list of DbSets within the context.
/// </value>
[ImportMany("Sets", typeof (DbSet<object>), AllowRecomposition = true)]
private List<object> TableObjects { get; set; }
/// <summary>
/// Composes the sets list.
/// </summary>
/// <remarks>
/// To make this work, you need to import the DbSets into a temporary collection of
/// DbSet of type "object", then cast this collection to DbSet of your required
/// interface type. For basic purposes, the IEntity interface will suffice.
/// </remarks>
private void ComposeSetsList()
{
// Instantiate the list of tables.
Tables = new List<DbSet<IEntity>>();
// Instantiate the MEF Import collection.
TableObjects = new List<object>();
// Create a new Types catalogue, to hold the exported parts.
var catalogue = new TypeCatalog(typeof (DbSet<object>));
// Create a new Composition Container, to match all the importable and imported parts.
var container = new CompositionContainer(catalogue);
// Compose the exported and imported parts for this class.
container.ComposeParts(this);
// Safe cast each DbSet<object> to the public list as DbSet<IEntity>.
TableObjects.ForEach(p => Tables.Add(p as DbSet<IEntity>));
}
#endregion
接下來,運行從構造的CompileSetsList()
門面(如圖中的Web最佳實踐):
public MvcApplicationContext()
{
// Enable verification of transactions for ExecuteSQL functions.
Configuration.EnsureTransactionsForFunctionsAndCommands = true;
// Disable lazy loading.
Configuration.LazyLoadingEnabled = false;
// Enable tracing of SQL queries.
Database.Log = msg => Trace.WriteLine(msg);
// Use MEF to compile a list of all sets within the context.
ComposeSetsList();
}
然後,只是裝飾你的DbSet <>就像這樣:
/// <summary>
/// Gets or sets the job levels.
/// </summary>
/// <value>
/// The job levels.
/// </value>
[Export("Sets", typeof(DbSet<object>))]
public DbSet<JobLevel> JobLevels { get; set; }
現在它會正常工作。
在不同的上下文中完全不同的方法,但也許對你有趣:http://stackoverflow.com/questions/9762808/change-fluent-api-mapping-dynamically – 2012-03-27 18:59:50