In this post, i will show how to use generic repository and dependency injection using structuremap. I will be using LINQ to SQL.

Generic Repository

The interface for the generic repository is like this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
public interface IRepository<T> where T : class
    {
        void Create(T entity);
        void Update(T entity);
        void Delete(T entity);
        void Copy(T source, T target);
        void Flush();
 
        T Get(Expression<Func<T, bool>> predicate);
        IEnumerable<T> GetAll();
 
        System.Data.Linq.Table<T> Table { get; }
 
        int Count(Expression<Func<T, bool>> predicate);
        IEnumerable<T> Fetch(Expression<Func<T, bool>> predicate);
        IEnumerable<T> Fetch(Expression<Func<T, bool>> predicate, Action<Orderable<T>> order);
        IEnumerable<T> Fetch(Expression<Func<T, bool>> predicate, Action<Orderable<T>> order, int skip, int count);
 
    }

Now lets go to the implementation of the generic repository interface.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
public class Repository<T> : IRepository<T> where T : class
    {
 
        protected IDataContextFactory _dataContextFactory;
 
        public Repository(IDataContextFactory dataContextFactory)
        {
            _dataContextFactory = dataContextFactory;
        }
 
        public System.Data.Linq.Table<T> Table
        {
            get { return _dataContextFactory.Context.GetTable<T>(); }
 
        }
 
        IEnumerable<T> IRepository<T>.GetAll()
        {
            return Table.ToReadOnlyCollection();
        }
 
        #region IRepository<T> Members
 
        void IRepository<T>.Create(T entity)
        {
            Table.InsertOnSubmit(entity);
            _dataContextFactory.SaveAll();
        }
 
        void IRepository<T>.Update(T entity)
        {
            if (Table.GetOriginalEntityState(entity) == null)
            {
                Table.Attach(entity);
            }
            _dataContextFactory.Context.Refresh(System.Data.Linq.RefreshMode.KeepCurrentValues, entity);
            _dataContextFactory.SaveAll();
        }
 
        void IRepository<T>.Delete(T entity)
        {
            Table.DeleteOnSubmit(entity);
            _dataContextFactory.SaveAll();
        }
 
       T IRepository<T>.Get(Expression<Func<T, bool>> predicate)
        {
            return Table.FirstOrDefault(predicate);
        }
 
        int IRepository<T>.Count(Expression<Func<T, bool>> predicate)
        {
            return Table.Count(predicate);
        }
 
        public virtual IQueryable<T> Fetch(Expression<Func<T, bool>> predicate)
        {
            return Table.Where(predicate);
        }
 
        public virtual IQueryable<T> Fetch(Expression<Func<T, bool>> predicate, Action<Orderable<T>> order)
        {
            var orderable = new Orderable<T>(Fetch(predicate));
            order(orderable);
            return orderable.Queryable;
        }
 
        public virtual IQueryable<T> Fetch(Expression<Func<T, bool>> predicate, Action<Orderable<T>> order, int skip, int count)
        {
            return Fetch(predicate, order).Skip(skip).Take(count);
        }
 
        IEnumerable<T> IRepository<T>.Fetch(Expression<Func<T, bool>> predicate)
        {
            return Fetch(predicate).ToReadOnlyCollection();
        }
 
        IEnumerable<T> IRepository<T>.Fetch(Expression<Func<T, bool>> predicate, Action<Orderable<T>> order)
        {
            return Fetch(predicate, order).ToReadOnlyCollection();
        }
 
        IEnumerable<T> IRepository<T>.Fetch(Expression<Func<T, bool>> predicate, Action<Orderable<T>> order, int skip, int count)
        {
            return Fetch(predicate, order, skip, count).ToReadOnlyCollection();
        }
 
        #endregion
     }

If you notice ToReadOnlyCollection() this is an extension method of the IEnumerable. This is defined as:

1
2
3
4
5
6
using System.Collections.ObjectModel;
 
 public static IList<T> ToReadOnlyCollection<T>(this IEnumerable<T> enumerable)
        {
            return new ReadOnlyCollection<T>(enumerable.ToList());
        }

I think thats if for our generic repository. To use it, for example if we have a Blog model on our LINQ to SQL we can use the repository like:

1
IRepository<Blog> BlogRepository = new Repository<Blog>();

Using StructureMap Dependency Injector

Before reading this, I assume that the reader has knowledge already about dependency injection.

First we have to reference the StructureMap DLL. It can be downloaded on the structuremap website.

Then we have to create the Registry Class. This class will configure the dependencies. This class should be of type StructureMap.Configuration.DSL.Registry

The Registry class may look like this:

1
2
3
4
5
6
7
8
public class ApplicationRegistry : Registry
    {
        public ApplicationRegistry()
        {
            For(typeof(IRepository<Blog>)).Use(typeof(Repository<Blog>));
            For(typeof(IDataContextFactory)).Use(typeof(DataContext));
        }
    }

After configuring the dependency, we will going to add our Registry to the StructureMap configuration. Usually, this will be on a Bootstrapper class that looks like this:

1
2
3
4
5
6
7
8
9
10
public static class Bootstrapper
    {
        public static void ConfigureStructureMap()
        {
            ObjectFactory.Initialize(x =>
            {
                x.AddRegistry(new ApplicationRegistry());
            });
        }
    }

This code tells the application to use the dependency injection as configure on the registry class. This should be called on program startup, the main method on console application or on global.asax on web application.

1
Bootstrapper.ConfigureStructureMap();

To get the instance of the repository:

1
IRepository<Blog> Repository = ObjectFactory.GetInstance<IRepository<Blog>>();

That should be it. Its ready.

If you have questions, please leave comments. I would be happy to answer.

If you want to create test repository that give predictable data, you should have another configuration for your test. Another boot strapper class perhaps but this is for test specific repository configuration. And on your test project call the test boot strapper not the original one.

Or just use mocking for testing like my code below using MOQ:

[TestMethod] public void GetUserByIDTest() { User user = new User() { UserID = 1, UserName = “mcxiand”, Password = “password”, }; var userid = 1; //initialize mock var mock = new Mock<IRepository>(); //see if the method in something you have mocked has been called by using Verify(). mock.Setup(x => x.Get(It.IsAny<Expression<Func>>())).Returns(user);

//Initialize Service service = new UserService(mock.Object); //call the method to test var u = service.GetUser(userid);

//Assert Assert.AreEqual(u.UserID, userid, “not equal”); }

http://mcxiand.wordpress.com/2010/05/13/using-structuremap-di-and-generic-repository/

Using StructureMap DI and Generic Repository的更多相关文章

  1. Generic repository pattern and Unit of work with Entity framework

    原文 Generic repository pattern and Unit of work with Entity framework Repository pattern is an abstra ...

  2. EF6 CodeFirst+Repository+Ninject+MVC4+EasyUI实践(完)

    前言 这一篇是本系列的最后一篇,虽然示例讲到这里就停止呢,但对于这些技术的学习远不能停止.虽然本示例讲的比较基础,但是正如我第一篇说到的,这个系列的目的不是说一些高端的架构设计,而是作为一个入门级,对 ...

  3. Follow me to learn what is repository pattern

    Introduction Creating a generic repository pattern in an mvc application with entity framework is th ...

  4. Using the Repository Pattern with ASP.NET MVC and Entity Framework

    原文:http://www.codeguru.com/csharp/.net/net_asp/mvc/using-the-repository-pattern-with-asp.net-mvc-and ...

  5. [转]Using the Repository Pattern with ASP.NET MVC and Entity Framework

    本文转自:http://www.codeguru.com/csharp/.net/net_asp/mvc/using-the-repository-pattern-with-asp.net-mvc-a ...

  6. Using the Repository and Unit Of Work Pattern in .net core

    A typical software application will invariably need to access some kind of data store in order to ca ...

  7. 单元操作和仓储模式 repository+unitOfWork

    仓储和工作单元模式是用来在数据访问层和业务逻辑层之间创建一个抽象层.应用这些模式,可以帮助用来隔离你的程序在数据存储变化. 在数据源层和业务层之间增加一个repository层进行协调,有如下作用:1 ...

  8. 6.在MVC中使用泛型仓储模式和依赖注入实现增删查改

    原文链接:http://www.c-sharpcorner.com/UploadFile/3d39b4/crud-operations-using-the-generic-repository-pat ...

  9. MVC中使用泛型仓储模式和依赖注入

    在ASP.NET MVC中使用泛型仓储模式和依赖注入,实现增删查改 原文链接:http://www.codeproject.com/Articles/838097/CRUD-Operations-Us ...

随机推荐

  1. LeetCode OJ 226. Invert Binary Tree

    Invert a binary tree. 4 / \ 2 7 / \ / \ 1 3 6 9 to 4 / \ 7 2 / \ / \ 9 6 3 1 Trivia:This problem was ...

  2. 更改Xcode的缺省公司名

    更改前: //  testAppDelegate.m //  test // //  Created by gaohf on 11-5-24. //  Copyright 2011 __MyCompa ...

  3. PHP文件相关函数试题

    一.问答题 1.返回路径中的文件名部分的函数是什么? 2.改变文件模式的函数是什么? 3.拷贝文件的函数是什么? 4.返回路径中的目录部分的函数是什么? 5.将上传的文件移动到指定位置的函数是? 6. ...

  4. NDK编译应用程序

    Android源码目录下的build/envsetup.sh文件,描述编译的命令 - m:       Makes from the top of the tree. - mm:      Build ...

  5. 两种方法将oracle数据库中的一张表的数据导入到另外一个oracle数据库中

    oracle数据库实现一张表的数据导入到另外一个数据库的表中的方法有很多,在这介绍两个. 第一种,把oracle查询的数据导出为sql文件,执行sql文件里的insert语句,如下: 第一步,导出sq ...

  6. 多线程junit单元测试

    junit中测试完成后会进行jvm退出,而不是线程退出,所以任一线程退出都会导致测试结束,junit想进行多线程测试需要进行另外包装,网上看到一个投机取巧的例子还不错,贴上我的测试代码(代码中我需要测 ...

  7. php 四种基础算法 ---- 选择排序法

    2. 选择排序法: 选择排序法思路: 每次选择一个相应的元素,然后将其放到指定的位置 代码: function select_sort($arr) {//实现思路 双重循环完成,外层控制轮数,当前的最 ...

  8. Android自定义XML属性

    <?xml version="1.0" encoding="utf-8"?> <resources> <declare-style ...

  9. Spring中管理Bean以及解析XML

    Spring是分层的轻量级框架 以IoC(Inverse of Control 反转控制)和AOP(Aspect Oriented Programming 面向切面编程)为核心 应用Spring的好处 ...

  10. Callable、Future和FutureTask区别

    在前面的文章中我们讲述了创建线程的2种方式,一种是直接继承Thread,另外一种就是实现Runnable接口. 这2种方式都有一个缺陷就是:在执行完任务之后无法获取执行结果. 如果需要获取执行结果,就 ...