在MVC中使用Unity。如何在其他地方注入其依赖项?

时间:2012-02-27 10:11:04

标签: model-view-controller dependency-injection unity-container console-application

我已经在我的MVC项目中使用Unity一段时间了,成功地注入了像这样的依赖项:

public interface IDepartmentRepository
{
 //blah blah
} 
public class DepartmentRepository: IDepartmentRepository
{
// blah blah
}

进入控制器并使用它们使用EF CodeFirst在SQL Compact数据库上进行CRUD,还使用NLog进行日志记录,以及为我的应用程序执行其他操作。

但是如果我想将MVC webapp之外的内容注入控制台应用程序呢?当我这样做时,我似乎错过了一些东西:

class Program
{
    static void Main(string[] args)
    {
        UnityContainer container = new UnityContainer();

        container.RegisterType<IContext, SCSMContext>(new PerResolveLifetimeManager());
        container.RegisterType<IOrderRepository, OrderRepository>();
        container.RegisterType<ILogger, NLogLogger>();
        container.RegisterType<IDoSomething, DoSomething>();

        DoSomething foo = (DoSomething)container.Resolve<IDoSomething>();

    }
}

public interface IDoSomething
{
}

class DoSomething: IDoSomething
{
    IOrderRepository orderRepository;
    IOrderFileUploadRepository orderFileUploadRepository;
    IContext unitOfWork;
    ILogger logger;

    public DoSomething(IOrderRepository orderRepository,
                       IContext unitOfWork, 
                       ILogger logger)
    {
        this.orderRepository = orderRepository;
        this.unitOfWork = unitOfWork;
        this.logger = logger;

        logger.LogInfo("Logging from an external project!");
        orderRepository.Add(new Order() {OrderName="foo"});
        unitOfWork.CommitChanges();
        // These lines run and give no exceptions
        // But nothing gets logged or inserted

        orderRepository.GetAll();
        //Returns an empty list, when there are orders in db.
    }
}

}

谢谢!

修改

ILogger和NLogLogger类:

public interface ILogger
{                    
    void LogInfo(string message, params object[] args);       
    void LogWarning(string message, params object[] args);  
    void LogError(string message, Exception exception, params object[] args);
}


public class NLogLogger : ILogger
{
    private Logger _logger;

    public NLogLogger()
    {
        _logger = LogManager.GetCurrentClassLogger();
    }

    public void LogInfo(string message, params object[] args)
    {
        _logger.Info(message);
    }

    public void LogWarning(string message, params object[] args)
    {
        _logger.Warn(message);
    }

    public void LogError(string message, Exception exception, params object[] args)
    {
        _logger.Error(message + LogUtility.BuildExceptionMessage(exception));
    }
}

注意:这个项目是其他人工作的项目,然后离开.. 我还在弄清楚整个事情是如何起作用的,如果我忽略了一些事情就很抱歉。

IContext和SCSMContext类似乎有点太深刻了,我无法完全掌握,在这里他们去了:

IContext:

public interface IContext : IQueryableUnitOfWork
{

    IDbSet<Location> Locations { get; }
    IDbSet<Department> Departments { get; }

    IDbSet<Requisition> Requisitions { get; }
    IDbSet<RequisitionAttachment> RequisitionAttachments { get; }
    IDbSet<RequisitionItem> RequisitionItems { get; }
    IDbSet<RequisitionComment> RequisitionComments { get; }

    IDbSet<Order> Orders{ get; }
    IDbSet<OrderItem> OrderItems { get; }
    IDbSet<OrderFileUpload> OrderFileUploads { get; }

    IDbSet<Transaction> Transactions { get; }

    IDbSet<DispatchNote> DispatchNotes { get; }
    IDbSet<DispatchItem> DispatchItems { get; }

    IDbSet<LocationsInRolesForUser> LocationsInRolesForUser { get; }

}

SCSMContext:

public class SCSMContext : System.Data.Entity.DbContext, IContext
{
    #region IContext Members

    IDbSet<Order> _orders;
    public IDbSet<Order> Orders
    {
        get
        {
            if (_orders == null)
                _orders = base.Set<Order>();

            return _orders;
        }
    }

    //Other IContext definitions......

    #endregion



    #region IQueryableUnitOfWork Members

    public IDbSet<T> CreateSet<T>()
               where T : class
    {
        return base.Set<T>();
    }

    public void Attach<T>(T item)
        where T : class
    {
        //attach and set as unchanged
        base.Entry<T>(item).State = System.Data.EntityState.Unchanged;
    }

    public void SetModified<T>(T item)
        where T : class
    {
        //this operation also attach item in object state manager
        base.Entry<T>(item).State = System.Data.EntityState.Modified;
    }

    public void ApplyCurrentValues<T>(T original, T current)
        where T : class
    {
        //if not is attached, attach original and set current values
        base.Entry<T>(original).CurrentValues.SetValues(current);
    }

    public void CommitChanges()
    {
        base.SaveChanges();
    }

    public void RollbackChanges()
    {
        // set all entities in change tracker 
        // as 'unchanged state'
        base.ChangeTracker.Entries()
                          .ToList()
                          .ForEach(entry => entry.State = System.Data.EntityState.Unchanged);
    }

    public IEnumerable<T> ExecuteQuery<T>(string sqlQuery, params object[] parameters)
    {
        return base.Database.SqlQuery<T>(sqlQuery, parameters);
    }

    public int ExecuteCommand(string sqlCommand, params object[] parameters)
    {
        return base.Database.SqlCommand(sqlCommand, parameters);
    }

    #endregion


}

另外,IQueryableUnitOfWork:(以防万一?)

public interface IQueryableUnitOfWork : IUnitOfWork, ISql
{
    /// <summary>
    /// Returns a IDbSet instance for access to entities of the given type in the context, 
    /// the ObjectStateManager, and the underlying store. 
    /// </summary>
    /// <typeparam name="T"></typeparam>
    /// <returns></returns>
    IDbSet<T> CreateSet<T>() where T : class;

    /// <summary>
    /// Attach this item into "ObjectStateManager"
    /// </summary>
    /// <typeparam name="T">The type of entity</typeparam>
    /// <param name="item">The item <</param>
    void Attach<T>(T item) where T : class;

    /// <summary>
    /// Set object as modified
    /// </summary>
    /// <typeparam name="T">The type of entity</typeparam>
    /// <param name="item">The entity item to set as modifed</param>
    void SetModified<T>(T item) where T : class;

    /// <summary>
    /// Apply current values in <paramref name="original"/>
    /// </summary>
    /// <typeparam name="T">The type of entity</typeparam>
    /// <param name="original">The original entity</param>
    /// <param name="current">The current entity</param>
    void ApplyCurrentValues<T>(T original, T current) where T : class;
}

对于这个庞大的帖子感到抱歉:\

1 个答案:

答案 0 :(得分:0)

似乎我需要更多说明:为什么要将调用的结果转换为DoSomething?您不会将上下文注入存储库。我猜想存储库需要上下文才能运行。我不熟悉NLog,但是如果它与Log4Net类似,你需要更多的配置(比如app.config中的专用部分或代码中的显式设置)来告诉框架在哪里记录(文件,数据库,事件日志) ,...)和使用什么记录器(平面文件记录器,滚动文件记录器......)而不是简单地调用LogManager.GetCurrentClassLogger