我已经在我的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;
}
对于这个庞大的帖子感到抱歉:\
答案 0 :(得分:0)
似乎我需要更多说明:为什么要将调用的结果转换为DoSomething
?您不会将上下文注入存储库。我猜想存储库需要上下文才能运行。我不熟悉NLog,但是如果它与Log4Net类似,你需要更多的配置(比如app.config中的专用部分或代码中的显式设置)来告诉框架在哪里记录(文件,数据库,事件日志) ,...)和使用什么记录器(平面文件记录器,滚动文件记录器......)而不是简单地调用LogManager.GetCurrentClassLogger