Autofac通用工厂

时间:2016-02-11 06:21:15

标签: c# entity-framework dependency-injection autofac

我开发Web应用程序,我的数据访问首先使用Entity framework 6代码

我在DataService层中有这些依赖项:

public DataService(IRepository<Folder> folders, IRepository<Letter> letters, IRepository<Destination> destinations)

在这些依赖关系中,我分别注入以下类型:

FoldersRepository,

LettersRepository,

DestinationsRepository

我需要每个请求生命周期的那些存储库。有没有办法用一个更好的方式为他们注入Autofac(对于一个案例我将添加更多的存储库和未来)

我不想从我的DAL引用到Autofac。

编辑:这就是我想要的:

public IRepository<T> where T: BaseEntityObject
{
    void Add(T entity);

    void Remove(T entity);

    List<T> Get();

    T FindById(int id);

    int SaveChanges();

    void Dispose();

}


public abstract class EFRepository<T> : IRepository<T>
{
    protected readonly DbContext Context;

    public EFRepository(DbContext context)
    {
        Context = context;
    }

    public abstract List<T> Get();

    public void Add(T item)
    {
        Context.Set<T>().Add(item);
    }

    public void Remove(T item)
    {
        Context.Set<T>().Remove(item);
    }

    public void Update(T item)
    {
        Context.Entry(item).State = EntityState.Modified;
    }

    public void Dispose()
    {
        Context.Dispose();
    }

    public int SaveChanges()
    {
        return Context.SaveChanges();
    }

    public T FindById(int id)
    {
        return Context.Set<T>().Find(id); 
    }
}


public LettersRepository : EFRepository<Letter>
{
    public LettersRepository(DbContext context) : base(context) {}

    // Override for case includes will be needed in future
    public override List<T> Get()
    {
        return Context.Set<T>().ToList();
    }
}

public FoldersRepository : EFRepository<Folder>
{
    public FoldersRepository(DbContext context) : base(context) {}

    public override List<T> Get()
    {
        return Context.Set<T>().Include("Letters").ToList();
    }
}


public class DataService
{
    private IRepositoriesFactory _repositoriesFactory;

    public DataService(IRepositoriesFactory repositoriesFactory)
    {
        _repositoriesFactory = repositoriesFactory;
    }

    public bool AddFolder(Folder folder)
    {
        var isAdded = false;

        using (var foldersRepository = _repositoriesFactory.Create<FoldersRepository>)
        {
            if (foldersRepository.Add(folder))
            {
                foldersRepository.SaveChanges();
                isAdded = true;
            }
            else
            {
                Log("folder couldn't be addded");
            }
        }

        return isAdded;
    }
}

    public bool AddLetter(Letter letter)
    {
        var isAdded = false;

        using (var lettersRepository = _repositoriesFactory.Create<LettersRepository>)
        {
            if (lettersRepositoryv.Add(folder))
            {
                lettersRepository.SaveChanges();
                isAdded = true;
            }
            else
            {
                Log("letter couldn't be addded");
            }
        }

        return isAdded;
    }

    // More methods that manipulates data...
}

// This layer is not in my DAL project (the one using EF), Data service is the API supplier for DAL
public class DataAccessLayer
{
    private IDataService _dataService

    public DataAccessLayer(IDataService dataService)
    {
        _dataService = dataService
    }

    public void HandleAddFolderRequest(AddFolderRequestMessage msg)
    {
        if (!_dataService.AddFolder(msg.Folder))
        {
            Log ("Adding folder failed");
            Broadcast(new AddFolderResponseMessage());
            return;
        }

        Log("Adding folder succeeded");
        Broadcast(new AddFolderResponseMessage(true));      
    }

    public void HandleAddLetterRequest(AddLetterRequestMessage msg)
    {
        if (!_dataService.AddLetter(msg.letter))
        {
            Log ("Adding letter failed");
            Broadcast(new AddLetterResponseMessage());
            return;
        }

        Log("Adding letter succeeded");
        Broadcast(new AddLetterResponseMessage(true));      
    }

    public void HandleGetAllFolderLetters(GetFolderRequestMessage msg)
    {
        var letters = _dataService.GetFolderLetters(msg.FolderId);

        if (letters == null)
        {
            Log ("Could not get the folder's letters");
            Broadcast(new GetFolderResponseMessage());
            return;
        }

        Log("Got the folder's letters successfull");
        Broadcast(new GetFolderResponseMessage(true));      
    }

    // And so on.. more data manipulatation handling methods
}


// The Part I dont know how and where to implement

public interface IRepositoriesFactory
{
    T Create<T>() where T : class 
}

public class RepositoriesFactory : IRepositoriesFactory
{
    public T Create<T>() where T : class
    {
        // THE MAGIC HAPPENS HERE
    }
}

2 个答案:

答案 0 :(得分:1)

这只是为了说明,可能与回答问题无关。

假设这是一个MVC网站项目:

你会有一个控制器。

E.g HomeController

让我们说HomeContoller负责仪表板并向您展示各种有趣的信息。

所以我们需要数据......

class HomeContoller
{
     ServiceClass1  _serviceClass1
     public HomeContoller(ServiceClass1  serviceClass1)
     {
         _serviceClass1 = serviceClass1;
     }

     public ActionResult Index()
     { 
         var data = _serviceClass1.GetFancyData();
         return View(data);
     }


}

这是您可以使这或多或少变得复杂的基础知识......就像您的情况一样,您希望在服务层执行此操作。在这一点上,我不知道这是不是一个好主意......但是读别人评论我认为不是。

无论如何,这里的重点是我试图向您展示在DataService中使用DI类型代码构造和实例是没有意义的。

随着问题的出现,我将对此进行扩展。

更新示例!!!

public class FolderService
{
    private IFoldersRepository _foldersRepository;

    public FolderService(IFoldersRepository foldersRepository)
    {
        _foldersRepository = foldersRepository;
    }

    public bool SaveFolder(Folder folder)
    {
        if (folder == null)
            return false;

        if (folder.Id == 0)
        {
            folder.CreateOnDate = DateTime.Now;
            _foldersRepository.Folders.Add(folder);
        }

        //change this to cast the SaveChanges to bool
        // also not so sure this is a gd idea... bt thats by the by for this....
        //---------------------
        try 
        {
            _foldersRepository.SaveChanges();
            return true;
        }
        catch(exception ex)
        {
            return false;
        }
        //---------------------
    }
}

答案 1 :(得分:0)

首先,您应该只将autofac安装到驱动程序项目(顶部),然后在那里注册您的课程。所有其他项目都应该使用接口。

然后你可以使用通用注册。

builder.RegisterGeneric(typeof(Repository<>)).As(typeof(IRepository<>)).InstancePerLifetimeScope();