我会考虑使用一种plugin
架构,因为这是您对应用程序本身的总体设计。
您可以通过执行以下操作来完成此基础知识(请注意,此示例使用StructureMap
- 这是StructureMap 文档的链接):
创建一个接口,您的DbContext
对象可以从中派生。
public interface IPluginContext {
IDictionary<String, DbSet> DataSets { get; }
}
在您的依赖注入设置中(使用 StructureMap) - 执行以下操作:
Scan(s => {
s.AssembliesFromApplicationBaseDirectory();
s.AddAllTypesOf<IPluginContext>();
s.WithDefaultConventions();
});
For<IEnumerable<IPluginContext>>().Use(x =>
x.GetAllInstances<IPluginContext>()
);
对于您的每个插件,要么更改{plugin}.Context.tt
文件,要么添加一个partial class
文件,使DbContext
生成的文件派生自IPluginContext
.
public partial class FooContext : IPluginContext { }
更改{plugin}.Context.tt
每个插件的文件以公开如下内容:
public IDictionary<String, DbSet> DataSets {
get {
// Here is where you would have the .tt file output a reference
// to each property, keyed on its property name as the Key -
// in the form of an IDictionary.
}
}
您现在可以执行以下操作:
// This could be inside a service class, your main Data Context, or wherever
// else it becomes convenient to call.
public DbSet DataSet(String name) {
var plugins = ObjectFactory.GetInstance<IEnumerable<IPluginContext>>();
var dataSet = plugins.FirstOrDefault(p =>
p.DataSets.Any(ds => ds.Key.Equals(name))
);
return dataSet;
}
如果语法不完美,请原谅我 - 我在帖子中执行此操作,而不是在编译器中。
最终结果使您可以灵活地执行以下操作:
// Inside an MVC controller...
public JsonResult GetPluginByTypeName(String typeName) {
var dataSet = container.DataSet(typeName);
if (dataSet != null) {
return Json(dataSet.Select());
} else {
return Json("Unable to locate that object type.");
}
}
显然,从长远来看 - 您会希望控件被反转,其中插件是实际绑定到架构中的插件,而不是服务器期望类型。但是,您可以使用这种延迟加载来完成同样的事情 - 主应用程序公开一个所有插件都绑定到的端点。
那将是这样的:
public interface IPlugin : IDisposable {
void EnsureDatabase();
void Initialize();
}
您现在可以将此接口公开给任何将为您的架构(DNN 风格)创建插件的应用程序开发人员 - 您的StructureMap
配置工作如下:
Scan(s => {
s.AssembliesFromApplicationBaseDirectory(); // Upload all plugin DLLs here
// NOTE: Remember that this gives people access to your system!!!
// Given what you are developing, though, I am assuming you
// already get that.
s.AddAllTypesOf<IPlugin>();
s.WithDefaultConventions();
});
For<IEnumerable<IPlugin>>().Use(x => x.GetAllInstances<IPlugin>());
现在,当您初始化应用程序时,您可以执行以下操作:
// Global.asax
public static IEnumerable<IPlugin> plugins =
ObjectFactory.GetInstance<IEnumerable<IPlugin>>();
public void Application_Start() {
foreach(IPlugin plugin in plugins) {
plugin.EnsureDatabase();
plugin.Initialize();
}
}
您的每个IPlugin
对象现在都可以包含自己的数据库上下文,管理安装(如果需要)自己的数据库实例/表的过程,并优雅地处理自己。
显然这不是一个完整的解决方案——但我希望它能让你朝着一个有用的方向开始。:) 如果我可以帮助澄清这里的任何内容,请告诉我。