Использование Unity в MVC. Как внедрить свои зависимости в другом месте? - PullRequest
0 голосов
/ 27 февраля 2012

Я уже некоторое время использую Unity в своем проекте MVC, успешно внедряя зависимости, подобные этой:

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

, в контроллеры и использую их для выполнения CRUD в базе данных SQL Compact с использованием EF CodeFirst, а также ведение журналаиспользуя NLog и другие вещи для моего приложения.

Но что, если я захочу внедрить их вне веб-приложения MVC в консольное приложение?Кажется, я что-то упускаю, когда я делаю это:

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 голосов
/ 27 февраля 2012

Похоже, мне нужны дополнительные разъяснения: почему вы приводите результат вашего вызова к контейнеру в DoSomething?Вы не вводите свой контекст в хранилище.Я предполагаю, что хранилищу нужен контекст для функционирования.И я не знаком с NLog, но если он похож на Log4Net, вам понадобится дополнительная конфигурация (например, выделенный раздел в вашем app.config или явная настройка в коде), чтобы указать платформе, куда вести журнал (файл, база данных, журнал событий)., ...) и какой регистратор использовать (фиксатор плоских файлов, скользящий регистратор файлов, ...), чем простой вызов LogManager.GetCurrentClassLogger

...