EF ObjectContext, Сервис и Репозиторий - Руководящее время жизни контекста.

Если вы хотите избежать использования формы или ввода и ищете ссылку в виде кнопки, вы можете создать симпатичные ссылки для кнопки с оболочкой div, якорем и тегом h1. Возможно, вы захотите этого, поэтому можете свободно размещать кнопку ссылки вокруг своей страницы. Это особенно полезно для горизонтальных центрирующих кнопок и имеющих вертикально центрированный текст внутри них. Вот как это делается:

Ваша кнопка будет состоять из трех вложенных частей: оболочки div, якоря и h1, например:


Тогда в CSS ваш стиль должен выглядеть вот так:

.link-button-wrapper {
    width: 200px;
    height: 40px;
    box-shadow: inset 0px 1px 0px 0px #ffffff;
    border-radius: 4px;
    background-color: #097BC0;
    box-shadow: 0px 2px 4px gray;
    display: block;
    border:1px solid #094BC0;
}
.link-button-wrapper > a {
    display: inline-table;
    cursor: pointer;
    text-decoration: none;
    height: 100%;
    width:100%;
}
.link-button-wrapper > a > h1 {
    margin: 0 auto;
    display: table-cell;
    vertical-align: middle;
    color: #f7f8f8;
    font-size: 18px;
    font-family: cabinregular;
    text-align: center;
}

Вот a jsFiddle , чтобы проверить его и поиграть с ним.

Преимущества этой настройки: 1. Создание отображения div-оболочки: блок облегчает центрирование (с помощью поля: 0 авто) и позиционирование (в то время как тег < a> встроен и его труднее позиционировать и невозможно центрировать).

  1. Вы можете просто сделать < a> display: block, переместить его и стилизовать как кнопку, но тогда вертикальное выравнивание текста внутри него станет трудным.

  2. Это позволяет вам использовать ; a> display: inline-table и < h1> display: table-cell, что позволяет вам использовать вертикальное выравнивание: среднее по < h1> и центрируйте его вертикально (что всегда приятно при нажатии кнопки). Да, вы можете использовать отступы, но если вы хотите, чтобы размер кнопки изменялся динамически, это будет не так чисто.

  3. Иногда, когда вы встраиваете < a> в элемент div, кликабелен только текст, эта настройка делает всю кнопку нажатой.

  4. Вам не нужно иметь дело с формами, если вы просто пытаетесь перейти на другую страницу. Формы предназначены для ввода информации, и они должны быть зарезервированы для этого.

  5. Позволяет вам аккуратно разделить стили кнопок и текста друг от друга (преимущество растягивания? Конечно, но CSS может выглядеть неприятно, поэтому его приятно разложить).

Это определенно упростило мою жизнь, создав мобильный сайт для экранов переменного размера.

7
задан Paul Siersma 5 July 2012 в 08:25
поделиться

1 ответ

Я пойду сверху (презентатор) и опишу отношения между участниками.

Презентатор получает объект службы через зависимость. Функциональность сервиса описана в его контракте:

class Presenter 
{
  public Presenter(IService service)
  {
     ... 
  }
}

Реализация сервиса абстрагируется от конкретной реализации уровня доступа к данным. Обычно всякий раз, когда служба выполняет какое-либо действие, требующее взаимодействия с источником данных, она создает экземпляр единицы работы и удаляет ее по завершении.

interface IService
{
  void Do();
}

class Service : IService
{
  private readonly IUnitOfWorkFactory unitOfWorkFactory;
  public Service(IUnitOfWorkFactory unitOfWorkFactory)
  {
    this.unitOfWorkFactory = unitOfWorkFactory;
  }

  public void Do()
  {
    // Whenever we need to perform some data manipulation we create and later dispose
    // dispose unit of work abstraction. It is created through a factory to avoid 
    // dependency on particular implementation.
    using(IUnitOfWork unitOfWork = this.unitOfWorkFactory.Create())
    {
       // Unit of work holds Entity Framework ObjectContext and thus it used 
       // create repositories and propagate them this ObjectContext to work with
       IRepository repository = unitOfWork.Create<IRepository>();
       repository.DoSomethingInDataSource();

       // When we are done changes must be commited which basically means committing
       // changes of the underlying object context.
       unitOfWork.Commit();
    }
  }
}


/// <summary>
/// Represents factory of <see cref="IUnitOfWork"/> implementations.
/// </summary>
public interface IUnitOfWorkFactory
{
    /// <summary>
    /// Creates <see cref="IUnitOfWork"/> implementation instance.
    /// </summary>
    /// <returns>Created <see cref="IUnitOfWork"/> instance.</returns>
    IUnitOfWork Create();
}

/// <summary>
/// Maintains a list of objects affected by a business transaction and coordinates the writing out of 
/// changes and the resolution of concurrency problems.
/// </summary>
public interface IUnitOfWork : IDisposable
{
    /// <summary>
    /// Creates and initializes repository of the specified type.
    /// </summary>
    /// <typeparam name="TRepository">Type of repository to create.</typeparam>
    /// <returns>Created instance of the repository.</returns>
    /// <remarks>
    /// Created repositories must not be cached for future use because once this 
    /// <see cref="IUnitOfWork"/> is disposed they won't be able to work properly.
    /// </remarks>
    TRepository Create<TRepository>();

    /// <summary>
    /// Commits changes made to this <see cref="IUnitOfWork"/>.
    /// </summary>
    void Commit();
}

/// <summary>
/// Represents factory of <see cref="UnitOfWork"/>s. 
/// </summary>
public class UnitOfWorkFactory : IUnitOfWorkFactory
{
    private readonly IUnityContainer container;

    /// <summary>
    /// Initializes a new instance of the <see cref="UnitOfWorkFactory"/> class.
    /// </summary>
    /// <param name="container">
    /// Dependency injection container instance used to manage creation of repositories 
    /// and entity translators.
    /// </param>
    public UnitOfWorkFactory(IUnityContainer container)
    {
                 this.conainer = container;
    }


    /// <summary>
    /// Creates <see cref="IUnitOfWork"/> implementation instance.
    /// </summary>
    /// <returns>Created <see cref="IUnitOfWork"/> instance.</returns>
    public IUnitOfWork Create()
    {
        var unitOfWork = this.container.Resolve<UnitOfWork>();
        unitOfWork.SetupObjectContext();
        return unitOfWork;
    }

     ... other members elidged for clarity
}

Реализация IUnitOfWork получает экземпляр IUnityContainer, а затем создает дочерний контейнер и регистрирует там экземпляр ObjectContext. Этот дочерний контейнер будет использоваться для создания репозиториев и распространения ObjectContext.

Вот упрощенная реализация IUnitOfWork:

class UnitOfWork : IUnitOfWork
{
  private readonly IUnityContainer container;
  private ObjectContext objectContext;

  public UnitOfWork (IUnityContainer container)
  {
    this.container = container.CreateChildContainer();
  }

  public void SetupObjectContext()
  {
    this.objectContext = ... // Create object context here
    this.container.RegisterInstance(context.GetType(), context);
  }

  public void Create<TRepository>()
  {
    // As long as we registered created object context instance in child container
    // it will be available now to repositories during resolve
    return this.container.Resolve<TRepository>();
  }

  public void Commit()
  {
     this.objectContext.SaveChanges();
  }
}

class Repository : IRepository
{
  private readonly SomeObjectContext objectContext;

  public Repository(SomeObjectContext objectContext)
  {
    this.objectContext = objectContext;
  }

  public void DoSomethingInDataSource()
  {
    // You can use object context instance here to do the work
  }
}
24
ответ дан 6 December 2019 в 07:27
поделиться
Другие вопросы по тегам:

Похожие вопросы: