.Net框架搭建之2SQL Server MEF依赖注入 MVC Repository框架
Posted 真爱无限
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了.Net框架搭建之2SQL Server MEF依赖注入 MVC Repository框架相关的知识,希望对你有一定的参考价值。
MEF依赖注入简介
依赖注入对于开发人员来说,方便的就是不需要去关注具体的实现类,不需要去New实例对象,直接使用接口层就能让程序自动注入使用,当然,还有其他一些特点,比如web http同一个请求中可以设置同一个对象只实例化一次解决多个类中多次实例化对象浪费资源的问题。不多说,百度能得到更多 多的介绍,这边直接开工搭环境。
1、数据模型Model层创建
数据模型层,首先要创建数据库,再创建Model类。
创建数据库,表,添加一条测试数据
创建数据库
创建数据表
添加测试数据
我们已经知道有几层,所以,先把所有的类库项目全部先建立好,web为MVC的空项目,至于各层代码,分到各层再去处理
项目结构
各层依赖关系
好了,一般情况下,在这个框架里,我们只需要创建相应的Model类与数据库表相对应就行了,比如这个项目,我们只创建两个类:
SysUser.cs
/* ==============================================================================
* 功能描述:SysUserInfo
* 创 建 者:蒲奎民
* 创建日期:2016-08-29 15:58:13
* CLR Version :4.0.30319.42000
* ==============================================================================*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace InjectExample.Model
public partial class SysUser
public long ID get; set;
public string Name get; set;
public int Age get; set;
public string Remark get; set;
SysUserInfo.cs
/* ==============================================================================
* 功能描述:SysUserInfo
* 创 建 者:蒲奎民
* 创建日期:2016-08-29 15:58:13
* CLR Version :4.0.30319.42000
* ==============================================================================*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace InjectExample.Model
public partial class SysUserInfo
public long ID get; set;
public long SysUserId get; set;
public int LoginCount get; set;
public DateTime LastLoginTime get; set;
新建类时,里面会自动加入创建者信息,怎么加的,可参考:
VS2013修改模版、创建类模版文件参考:
http://blog.csdn.net/pukuimin1226/article/details/51685279
至此,Model类就创建完成。
2、底层公共方法层Component处理
这层可以说是在这个框架搭建中最复杂的,但是,创建完之后,不需要怎么改动的地方。
好,为了能满足框架代码需要引用的Nuget包,我这里列出一下。
2.1 添加Nuget包和 .Net程序集引用
<package id="EntityFramework" version="6.1.3" targetFramework="net45" />
<package id="EntityFramework.Extended" version="6.1.0.168" targetFramework="net45" />
<package id="Microsoft.AspNet.Mvc" version="5.2.3" targetFramework="net45" />
<package id="Microsoft.AspNet.Razor" version="3.2.3" targetFramework="net45" />
<package id="Microsoft.AspNet.WebApi.Client" version="5.2.3" targetFramework="net45" />
<package id="Microsoft.AspNet.WebApi.Core" version="5.2.3" targetFramework="net45" />
<package id="Microsoft.AspNet.WebApi.WebHost" version="5.2.3" targetFramework="net45" />
<package id="Microsoft.AspNet.WebPages" version="3.2.3" targetFramework="net45" />
<package id="Microsoft.Composition" version="1.0.30" targetFramework="net45" />
<package id="Microsoft.Web.Infrastructure" version="1.0.0.0" targetFramework="net45" />
<package id="Newtonsoft.Json" version="6.0.4" targetFramework="net45" />
在nuget管理器中添加完成就行。
所有项目都勾上,免得麻烦。
还有一些,要添加系统的程序集,比如 System.Web,System.Configuration等等。
2.2 创建mvc依赖注入相关类:
先添加一个扩展类ConfigurationExt.cs,用来加载bin目录下的所有程序集
/* ==============================================================================
* 功能描述:Configuration
* 创 建 者:蒲奎民
* 创建日期:2016-08-29 10:47:49
* CLR Version :4.0.30319.42000
* ==============================================================================*/
using System;
using System.Collections.Generic;
using System.Composition.Hosting;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Web;
namespace InjectExample.Component
public static class ConfigurationExt
/// <summary>
/// 或取应用程序 Bin 路径
/// </summary>
/// <param name="inWeb">是否 web 应用</param>
/// <returns></returns>
public static IList<Assembly> DefaultAssemblies(bool inWeb)
var exts = new[] "exe", "dll" ;
var dir = inWeb ? HttpRuntime.BinDirectory : AppDomain.CurrentDomain.BaseDirectory;
var ns = System.Reflection.MethodBase.GetCurrentMethod().DeclaringType.Namespace;//获取本类的命名空间
var nsStrs = ns.Split(new char[] '.' );//拆分要取命名空间前缀
var files = Directory.EnumerateFiles(dir, nsStrs[0] + "*", SearchOption.TopDirectoryOnly)
.Where(file => exts.Any(x => file.EndsWith(x, StringComparison.OrdinalIgnoreCase)))
.ToList();
return files.Select(Assembly.LoadFrom).ToList();
public static ContainerConfiguration WithDefaultAssemblies(this ContainerConfiguration configuration)
configuration.WithAssemblies(DefaultAssemblies(true));
return configuration;
public static bool IsInNamespace(this Type type, string namespaceFragment)
return type.Namespace != null && (type.Namespace.EndsWith("." + namespaceFragment) || type.Namespace.Contains("." + namespaceFragment + "."));
CompositionProvider.cs
/* ==============================================================================
* 功能描述:CompositionProvider
* 创 建 者:蒲奎民
* 创建日期:2016-08-29 10:33:07
* CLR Version :4.0.30319.42000
* ==============================================================================*/
using System;
using System.Collections.Generic;
using System.Composition;
using System.Composition.Hosting;
using System.Composition.Hosting.Core;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.ModelBinding;
using System.Web.Mvc;
namespace InjectExample.Component.Mvc
/// <summary>
/// Provides composition services to ASP.NET MVC by integrating DependencyResolver with
/// the Managed Extensibility Framework (MEF). This class is self-configuring and will be
/// enabled by simply being present in the application's Bin directory. Most applications
/// should not need to access this class.
/// </summary>
public static class CompositionProvider
static CompositionHost _container;
static ExportFactory<CompositionContext> _requestScopeFactory;
static IList<Assembly> _partAssemblies = new List<Assembly>();
/// <summary>
/// Used to override the default conventions for controller/part dependency injection.
/// Cannot be used in conjunction with any other methods on this type. Most applications
/// should not use this method.
/// </summary>
/// <param name="configuration">A configuration containing the controller types and other parts that
/// should be used by the composition provider.</param>
public static void SetConfiguration(ContainerConfiguration configuration)
if (configuration == null) throw new ArgumentNullException("configuration");
if (IsInitialized) throw new InvalidOperationException("Already initialized.");
// We add RSF with no conventions (overriding anything set as the default in configuration)
_container = configuration.CreateContainer();
var factoryContract = new CompositionContract(
typeof(ExportFactory<CompositionContext>),
null,
new Dictionary<string, object> "SharingBoundaryNames", new[] Boundaries.HttpRequest, Boundaries.DataConsistency, Boundaries.UserIdentity
);
_requestScopeFactory = (ExportFactory<CompositionContext>)_container.GetExport(factoryContract);
ConfigureMvc();
//ConfigureWebApi();
//static void ConfigureWebApi()
//
// System.Web.Http.GlobalConfiguration.Configuration.DependencyResolver = new ScopeHttpDependencyResolver();
//
static void ConfigureMvc()
if (DependencyResolver.Current.GetType().Name != "DefaultDependencyResolver")
throw new CompositionFailedException("MVC's DependencyResolver has been changed.");
DependencyResolver.SetResolver(new ScopeDependencyResolver());
FilterProviders.Providers.Remove(FilterProviders.Providers.OfType<FilterAttributeFilterProvider>().SingleOrDefault());
FilterProviders.Providers.Add(new ScopeFilterAttributeFilterProvider());
System.Web.Mvc.ModelBinderProviders.BinderProviders.Add(new ScopeModelBinderProvider());
public static Export<CompositionContext> CreateContext()
PostStartDefaultInitialize();
return _requestScopeFactory.CreateExport();
internal static CompositionContext Current
get
var current = CurrentInitialisedScope;
if (current == null)
current = _requestScopeFactory.CreateExport();
CurrentInitialisedScope = current;
return current.Value;
internal static Export<CompositionContext> CurrentInitialisedScope
get return (Export<CompositionContext>)HttpContext.Current.Items[typeof(CompositionProvider)];
private set HttpContext.Current.Items[typeof(CompositionProvider)] = value;
/// <summary>
/// Adds assemblies containing MEF parts to the composition provider.
/// </summary>
/// <param name="assemblies">Assemblies containing parts to add.</param>
public static void AddAssemblies(params Assembly[] assemblies)
AddAssemblies((IEnumerable<Assembly>)assemblies);
public static void AddAssemblies(IEnumerable<Assembly> assemblies)
if (assemblies == null) throw new ArgumentException("assemblies");
foreach (var assembly in assemblies)
AddAssembly(assembly);
public static void AddAssembly(Assembly assembly)
if (assembly == null) throw new ArgumentNullException("assembly");
_partAssemblies.Add(assembly);
internal static void PostStartDefaultInitialize()
if (!IsInitialized)
SetConfiguration(new MvcContainerConfiguration());
static bool IsInitialized
get return _requestScopeFactory != null;
CompositionScopeModule.cs
using Microsoft.Web.Infrastructure.DynamicModuleHelper;
/* ==============================================================================
* 功能描述:CompositionScopeModule
* 创 建 者:蒲奎民
* 创建日期:2016-08-29 11:53:26
* CLR Version :4.0.30319.42000
* ==============================================================================*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
namespace InjectExample.Component.Mvc
/// <summary>
/// Provides lifetime management for the <see cref="CompositionProvider"/> type.
/// This module is automatically injected into the ASP.NET request processing
/// pipeline at startup and should not be called by user code.
/// </summary>
public class CompositionScopeModule : IHttpModule
static bool _isInitialized;
/// <summary>
/// Register the module. This method is automatically called
/// at startup and should not be called by user code.
/// </summary>
public static void Register()
if (!_isInitialized)
_isInitialized = true;
DynamicModuleUtility.RegisterModule(typeof(CompositionScopeModule));
/// <summary>
/// Release resources used by the module.
/// </summary>
public void Dispose()
/// <summary>
/// Initialize the module.
/// </summary>
/// <param name="context">Application in which the module is running.</param>
public void Init(HttpApplication context)
context.EndRequest += DisposeCompositionScope;
CompositionProvider.PostStartDefaultInitialize();
static void DisposeCompositionScope(object sender, EventArgs e)
var scope = CompositionProvider.CurrentInitialisedScope;
if (scope != null)
scope.Dispose();
ExportModelBinderAttribute.cs
/* ==============================================================================
* 功能描述:ExportModelBinderAttribute
* 创 建 者:蒲奎民
* 创建日期:2016-08-29 11:55:36
* CLR Version :4.0.30319.42000
* ==============================================================================*/
using System;
using System.Collections.Generic;
using System.Composition;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Mvc;
namespace InjectExample.Component.Mvc
/// <summary>
/// Marks a type as being a model binder for a specified model type. The type decorated with
/// this attribute must implement the <see cref="IModelBinder"/> interface.
/// </summary>
[AttributeUsage(AttributeTargets.Class | AttributeTargets.Property | AttributeTargets.Field)]
public sealed class ExportModelBinderAttribute : ExportAttribute
public ExportModelBinderAttribute(Type modelType)
: base(ScopeModelBinderProvider.GetModelBinderContractName(modelType), typeof(IModelBinder))
MvcContainerConfiguration.cs
/* ==============================================================================
* 功能描述:MvcContainerConfiguration
* 创 建 者:蒲奎民
* 创建日期:2016-08-29 10:46:21
* CLR Version :4.0.30319.42000
* ==============================================================================*/
using System;
using System.Collections.Generic;
using System.Composition.Convention;
using System.Composition.Hosting;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading.Tasks;
using System.Web;
using System.Web.Http.Controllers;
using System.Web.Mvc;
namespace InjectExample.Component.Mvc
/// <summary>
/// A <see cref="ContainerConfiguration"/> that loads parts in the currently-executing ASP.NET MVC web application.
/// Parts are detected by namespace - classes in a ".Parts" namespace will be considered to be parts. These classes,
/// and any interfaces they implement, will be exported and shared on a per-HTTP-request basis. When resolving
/// dependencies, the longest public constructor on a part type will be used. The <see cref="ImportAttribute"/>,
/// <see cref="ExportAttribute"/> and associated MEF attributes can be applied to modify composition structure.
/// </summary>
/// <remarks>
/// This implementation emulates CompositionContainer and the composition-container based MVC
/// integration for all types under the Parts namespace, for controllers, and for model binders. This will
/// aid migration from one composition engine to the other, but this decision should be revisited if it
/// causes confusion.
/// </remarks>
public class MvcContainerConfiguration : ContainerConfiguration
MvcContainerConfiguration(IEnumerable<Assembly> assemblies, AttributedModelProvider reflectionContext)
if (assemblies == null) throw new ArgumentNullException("assemblies");
if (reflectionContext == null) throw new ArgumentNullException("reflectionContext");
this.WithDefaultConventions(reflectionContext);
this.WithAssemblies(assemblies);
/// <summary>
/// Construct an <see cref="MvcContainerConfiguration"/> using parts in the specified assemblies.
/// </summary>
/// <param name="assemblies">Assemblies in which to search for parts.</param>
public MvcContainerConfiguration(IEnumerable<Assembly> assemblies)
: this(assemblies, DefineConventions())
/// <summary>
/// Construct an <see cref="MvcContainerConfiguration"/> using parts in the main application assembly.
/// In some applications this may not be the expected assembly - in those cases specify the
/// assemblies explicitly using the other constructor.
/// </summary>
public MvcContainerConfiguration()
: this(ConfigurationExt.DefaultAssemblies(true))
internal static Assembly GuessGlobalApplicationAssembly()
return HttpContext.Current.ApplicationInstance.GetType().BaseType.Assembly;
private static AttributedModelProvider DefineConventions()
var rb = new ConventionBuilder();
rb.ForTypesDerivedFrom<IController>().Export();
rb.ForTypesDerivedFrom<IHttpController>().Export();
rb.ForTypesMatching(IsAPart)
.Export()
.ExportInterfaces();
return rb;
private static bool IsAPart(Type t)
return !t.IsAssignableFrom(typeof(Attribute)) && t.IsInNamespace("Parts");
RemoveHttpHeadModule.cs,这个和依赖注入没关系,是附加的功能
/* ==============================================================================
* 功能描述:RemoveHttpHeadModule
* 创 建 者:蒲奎民
* 创建日期:2016-08-29 11:57:06
* CLR Version :4.0.30319.42000
* ==============================================================================*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web;
namespace InjectExample.Component.Mvc
/// <summary>
/// 移除Server HTTP头
/// </summary>
public class RemoveHttpHeadModule : IHttpModule
void context_PreSendRequestHeaders(object sender, EventArgs e)
HttpContext.Current.Response.Headers.Remove("Server");
public void Dispose()
//throw new NotImplementedException();
public void Init(HttpApplication context)
//移除Server HTTP头
context.PreSendRequestHeaders += context_PreSendRequestHeaders;
ScopeDependencyResolver.cs
/* ==============================================================================
* 功能描述:ScopeDependencyResolver
* 创 建 者:蒲奎民
* 创建日期:2016-08-29 10:39:59
* CLR Version :4.0.30319.42000
* ==============================================================================*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Mvc;
namespace InjectExample.Component.Mvc
public class ScopeDependencyResolver : IDependencyResolver
public object GetService(Type serviceType)
object export;
try
if (!CompositionProvider.Current.TryGetExport(serviceType, null, out export))
return null;
catch
return null;
return export;
public IEnumerable<object> GetServices(Type serviceType)
return CompositionProvider.Current.GetExports(serviceType);
ScopeFilterAttributeFilterProvider.cs
/* ==============================================================================
* 功能描述:ScopeFilterAttributeFilterProvider
* 创 建 者:蒲奎民
* 创建日期:2016-08-29 10:40:54
* CLR Version :4.0.30319.42000
* ==============================================================================*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Mvc;
using System.Composition;
namespace InjectExample.Component.Mvc
class ScopeFilterAttributeFilterProvider : FilterAttributeFilterProvider
public ScopeFilterAttributeFilterProvider()
: base(cacheAttributeInstances: false)
protected override IEnumerable<FilterAttribute> GetActionAttributes(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
var attributes = base.GetActionAttributes(controllerContext, actionDescriptor).ToArray();
ComposeAttributes(attributes);
return attributes;
protected override IEnumerable<FilterAttribute> GetControllerAttributes(ControllerContext controllerContext, ActionDescriptor actionDescriptor)
var attributes = base.GetControllerAttributes(controllerContext, actionDescriptor).ToArray();
ComposeAttributes(attributes);
return attributes;
void ComposeAttributes(FilterAttribute[] attributes)
foreach (var attribute in attributes)
CompositionProvider.Current.SatisfyImports(attribute);
ScopeModelBinderProvider.cs
/* ==============================================================================
* 功能描述:ScopeModelBinderProvider
* 创 建 者:蒲奎民
* 创建日期:2016-08-29 10:45:30
* CLR Version :4.0.30319.42000
* ==============================================================================*/
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Web.Mvc;
namespace InjectExample.Component.Mvc
class ScopeModelBinderProvider : IModelBinderProvider
const string ModelBinderContractNameSuffix = "++ModelBinder";
public static string GetModelBinderContractName(Type modelType)
return modelType.AssemblyQualifiedName + ModelBinderContractNameSuffix;
public IModelBinder GetBinder(Type modelType)
IModelBinder export;
if (!CompositionProvider.Current.TryGetExport(GetModelBinderContractName(modelType), out export))
return null;
return export;
2.3 创建EF自定义实体映射相关底层类
主要是一些基层的单元操作、Repository公共接口和公共实现、DbContext类、数据库视图初始化等等。
DatabaseInitializer.cs
using InjectExample.Component.Mvc;
/* ==============================================================================
* 功能描述:DatabaseInitializer
* 创 建 者:蒲奎民
* 创建日期:2016-08-29 10:28:48
* CLR Version :4.0.30319.42000
* ==============================================================================*/
using System;
using System.Collections.Generic;
using System.Data.Entity;
using System.Data.Entity.Core.Mapping;
using System.Data.Entity.Core.Metadata.Edm;
using System.Data.Entity.Infrastructure;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace InjectExample.Component
/// <summary>
/// 数据库初始化操作类
/// </summary>
public static class DatabaseInitializer
/// <summary>
/// 数据库初始化
/// </summary>
public static void Initialize()
//关闭初始化
Database.SetInitializer<EfDbContext>(null);
/// <summary>
/// EF 预生成视图
/// </summary>
public static void PreCreateView()
using (var container = CompositionProvider.CreateContext())
var context = container.Value.GetExport<EfDbContext>();
var objectContext = ((IObjectContextAdapter)context).ObjectContext;
var collection = (StorageMappingItemCollection)objectContext.MetadataWorkspace.GetItemCollection(DataSpace.CSSpace);
collection.GenerateViews(new List<EdmSchemaError>());
EfDbContext.cs
/* ==============================================================================
* 功能描述:EfDbContext
* 创 建 者:蒲奎民
* 创建日期:2016-08-29 10:42:54
* CLR Version :4.0.30319.42000
* ==============================================================================*/
using System;
using System.Collections.Generic;
using System.Composition;
using System.Data.Entity;
using System.Data.Entity.ModelConfiguration.Conventions;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace InjectExample.Component
/// <summary>
/// EF数据访问上下文
/// </summary>
[Shared(Boundaries.DataConsistency)]
[Export(typeof(EfDbContext))]
public class EfDbContext : DbContext
public EfDbContext()
: base("InjextExampleEntities")//连接字符串名称
Configuration.LazyLoadingEnabled = false;
Configuration.ProxyCreationEnabled = false;
Configuration.ValidateOnSaveEnabled = false;
/// <summary>
/// 获取实现了IEntityMapper接口的entity mappers,用来注册到Db上下文
/// </summary>
[ImportMany]
public IEnumerable<IEntityMapper> EntityMappers get; set;
protected override void OnModelCreating(DbModelBuilder modelBuilder)
Configuration.ProxyCreationEnabled = false;
Configuration.LazyLoadingEnabled = false;
//Configuration.AutoDetectChangesEnabled = false;
//去掉一对多关系
modelBuilder.Conventions.Remove<OneToManyCascadeDeleteConvention>();
//去除生成表名复数
modelBuilder.Conventions.Remove<PluralizingTableNameConvention>();
//防止黑幕交易 要不然每次都要访问 (如果之前已经有数据库了,那么以上是关于.Net框架搭建之2SQL Server MEF依赖注入 MVC Repository框架的主要内容,如果未能解决你的问题,请参考以下文章
.Net框架搭建之1SQL Server EF MVC简单三层框架